diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml
index e072d66131..4c3b6d173b 100644
--- a/man/systemd-analyze.xml
+++ b/man/systemd-analyze.xml
@@ -551,7 +551,8 @@ NAutoVTs=8
systemd-analyze verify FILE...
This command will load unit files and print warnings if any errors are detected. Files specified
- on the command line will be loaded, but also any other units referenced by them. The full unit search
+ on the command line will be loaded, but also any other units referenced by them. A unit's name on disk
+ can be overridden by specifying an alias after a colon; see below for an example. The full unit search
path is formed by combining the directories for all command line arguments, and the usual unit load
paths. The variable $SYSTEMD_UNIT_PATH is supported, and may be used to replace or
augment the compiled in set of unit load paths; see
@@ -613,6 +614,27 @@ Service a.service not loaded, a.socket cannot be started.
Service b@0.service not loaded, b.socket cannot be started.
+
+
+ Aliasing a unit
+
+ $ cat /tmp/source
+[Unit]
+Description=Hostname printer
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/echo %H
+MysteryKey=true
+
+$ systemd-analyze verify /tmp/source
+Failed to prepare filename /tmp/source: Invalid argument
+
+$ systemd-analyze verify /tmp/source:alias.service
+/tmp/systemd-analyze-XXXXXX/alias.service:7: Unknown key name 'MysteryKey' in section 'Service', ignoring.
+
+
+
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
index 82fdd3deee..2d6d327f8d 100644
--- a/src/analyze/analyze.c
+++ b/src/analyze/analyze.c
@@ -26,6 +26,7 @@
#include "copy.h"
#include "def.h"
#include "exit-status.h"
+#include "extract-word.h"
#include "fd-util.h"
#include "fileio.h"
#include "filesystems.h"
@@ -42,6 +43,7 @@
#include "parse-util.h"
#include "path-util.h"
#include "pretty-print.h"
+#include "rm-rf.h"
#if HAVE_SECCOMP
# include "seccomp-util.h"
#endif
@@ -53,6 +55,7 @@
#include "strxcpyx.h"
#include "terminal-util.h"
#include "time-util.h"
+#include "tmpfile-util.h"
#include "unit-name.h"
#include "util.h"
#include "verb-log-control.h"
@@ -230,6 +233,53 @@ static int compare_unit_start(const UnitTimes *a, const UnitTimes *b) {
return CMP(a->activating, b->activating);
}
+static int process_aliases(char *argv[], char *tempdir, char ***ret) {
+ _cleanup_strv_free_ char **filenames = NULL;
+ char **filename;
+ int r;
+
+ assert(argv);
+ assert(tempdir);
+ assert(ret);
+
+ STRV_FOREACH(filename, strv_skip(argv, 1)) {
+ _cleanup_free_ char *src = NULL, *dst = NULL, *arg = NULL;
+ char *parse_arg;
+
+ arg = strdup(*filename);
+ if (!arg)
+ return -ENOMEM;
+
+ parse_arg = arg;
+ r = extract_first_word((const char **) &parse_arg, &src, ":", 0);
+ if (r < 0)
+ return r;
+
+ if (!parse_arg) {
+ r = strv_extend(&filenames, src);
+ if (r < 0)
+ return -ENOMEM;
+
+ continue;
+ }
+
+ dst = path_join(tempdir, basename(parse_arg));
+ if (!dst)
+ return -ENOMEM;
+
+ r = copy_file(src, dst, 0, 0644, 0, 0, COPY_REFLINK);
+ if (r < 0)
+ return r;
+
+ r = strv_consume(&filenames, TAKE_PTR(dst));
+ if (r < 0)
+ return -ENOMEM;
+ }
+
+ *ret = TAKE_PTR(filenames);
+ return 0;
+}
+
static UnitTimes* unit_times_free_array(UnitTimes *t) {
for (UnitTimes *p = t; p && p->has_data; p++)
free(p->name);
@@ -2257,7 +2307,19 @@ static int do_condition(int argc, char *argv[], void *userdata) {
}
static int do_verify(int argc, char *argv[], void *userdata) {
- return verify_units(strv_skip(argv, 1), arg_scope, arg_man, arg_generators, arg_recursive_errors, arg_root);
+ _cleanup_strv_free_ char **filenames = NULL;
+ _cleanup_(rm_rf_physical_and_freep) char *tempdir = NULL;
+ int r;
+
+ r = mkdtemp_malloc("/tmp/systemd-analyze-XXXXXX", &tempdir);
+ if (r < 0)
+ return log_error_errno(r, "Failed to setup working directory: %m");
+
+ r = process_aliases(argv, tempdir, &filenames);
+ if (r < 0)
+ return log_error_errno(r, "Couldn't process aliases: %m");
+
+ return verify_units(filenames, arg_scope, arg_man, arg_generators, arg_recursive_errors, arg_root);
}
static int do_security(int argc, char *argv[], void *userdata) {
diff --git a/test/units/testsuite-65.sh b/test/units/testsuite-65.sh
index 3218462c76..f98a933cb1 100755
--- a/test/units/testsuite-65.sh
+++ b/test/units/testsuite-65.sh
@@ -76,6 +76,14 @@ systemd-analyze verify /tmp/.testfile.service
rm /tmp/.testfile.service
+# Alias a unit file's name on disk (see #20061)
+cp /tmp/testfile.service /tmp/testsrvc
+
+systemd-analyze verify /tmp/testsrvc \
+ && { echo 'unexpected success'; exit 1; }
+
+systemd-analyze verify /tmp/testsrvc:alias.service
+
# Zero exit status since the value used for comparison determine exposure to security threats is by default 100
systemd-analyze security --offline=true /tmp/testfile.service