]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
systemd-analyze: add --root option for 'verify' verb and allow path parsing
authorMaanya Goenka <t-magoenka@microsoft.com>
Wed, 30 Jun 2021 16:57:54 +0000 (09:57 -0700)
committerMaanya Goenka <t-magoenka@microsoft.com>
Tue, 10 Aug 2021 09:41:12 +0000 (02:41 -0700)
-------------------------------------------------------------------------------
Example Run:

foobar.service created below is a service unit file that has a non-existing key-value
pairing (foo = bar) and is thus, syntactically invalid.

maanya-goenka@debian:~/systemd (img-support)$ cat <<EOF>img/usr/lib/systemd/system/foobar.service
> [Unit]
> foo = bar
>
> [Service]
> ExecStart = /opt/script0.sh
> EOF

The failure to create foobar.service because of the recursive dependency searching and verification has been addressed
in a different PR: systemd-analyze: add option to return an error value when unit verification fails #20233

maanya-goenka@debian:~/systemd (img-support)$ sudo build/systemd-analyze verify --root=img/ foobar.service
/home/maanya-goenka/systemd/img/usr/lib/systemd/system/foobar.service:2: Unknown key name 'foo' in section 'Unit', ignoring.
foobar.service: Failed to create foobar.service/start: Unit sysinit.target not found.

21 files changed:
man/systemd-analyze.xml
shell-completion/bash/systemd-analyze
shell-completion/zsh/_systemd-analyze
src/analyze/analyze-condition.c
src/analyze/analyze-verify.c
src/analyze/analyze-verify.h
src/analyze/analyze.c
src/core/main.c
src/core/manager.c
src/core/manager.h
src/test/test-bpf-firewall.c
src/test/test-bpf-foreign-programs.c
src/test/test-cgroup-mask.c
src/test/test-cgroup-unit-default.c
src/test/test-engine.c
src/test/test-execute.c
src/test/test-load-fragment.c
src/test/test-path.c
src/test/test-sched-prio.c
src/test/test-socket-bind.c
src/test/test-watch-pid.c

index 4da066e05c26854a032e0b0e5b0fcccc4a9f2380..21e2e928cf8b69cbae9612e61a39e9098e2cc5df 100644 (file)
@@ -747,8 +747,8 @@ Service b@0.service not loaded, b.socket cannot be started.
       <varlistentry>
         <term><option>--root=<replaceable>PATH</replaceable></option></term>
 
-        <listitem><para>With <command>cat-files</command>, show config files underneath
-        the specified root path <replaceable>PATH</replaceable>.</para></listitem>
+        <listitem><para>With <command>cat-files</command> and <command>verify</command>,
+        operate on files underneath the specified root path <replaceable>PATH</replaceable>.</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 36fcf432ff91b92ed675862802cbeca0ee523feb..e0a9ef5d15a162d94b3744085a4ac70a7b6e5d22 100644 (file)
@@ -125,7 +125,7 @@ _systemd_analyze() {
 
     elif __contains_word "$verb" ${VERBS[VERIFY]}; then
         if [[ $cur = -* ]]; then
-            comps='--help --version --system --user --global --man=no --generators=yes'
+            comps='--help --version --system --user --global --man=no --generators=yes --root'
         else
             comps=$( compgen -A file -- "$cur" )
             compopt -o filenames
index ce8e6162e810cfa9878b38c5f4595286e74b08be..921b6cb27d9b6e668869811175304b2e2459659e 100644 (file)
@@ -87,6 +87,7 @@ _arguments \
     '--system[Operate on system systemd instance]' \
     '--user[Operate on user systemd instance]' \
     '--global[Show global user instance config]' \
+    '--root=[Add support for root argument]:PATH' \
     '--no-pager[Do not pipe output into a pager]' \
     '--man=[Do (not) check for existence of man pages]:boolean:(1 0)' \
     '--order[When generating graph for dot, show only order]' \
index 241c188ed6d187a46198ebd2b56843af4fed99d3..09870b95ec497b1e28e34feb6dcad05eb7a45467 100644 (file)
@@ -83,7 +83,7 @@ int verify_conditions(char **lines, UnitFileScope scope) {
                 return log_error_errno(r, "Failed to initialize manager: %m");
 
         log_debug("Starting manager...");
-        r = manager_startup(m, NULL, NULL);
+        r = manager_startup(m, /* serialization= */ NULL, /* fds= */ NULL, /* root= */ NULL);
         if (r < 0)
                 return r;
 
index bb5bdf998a35cfcc32ce0a85188b9f5c17754aca..4fcec2fcdce8c988037199ef01b0d7a7e172dcff 100644 (file)
@@ -218,7 +218,7 @@ static int verify_unit(Unit *u, bool check_man) {
         return r;
 }
 
-int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run_generators) {
+int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run_generators, const char *root) {
         const ManagerTestRunFlags flags =
                 MANAGER_TEST_RUN_MINIMAL |
                 MANAGER_TEST_RUN_ENV_GENERATORS |
@@ -246,7 +246,7 @@ int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run
 
         log_debug("Starting manager...");
 
-        r = manager_startup(m, NULL, NULL);
+        r = manager_startup(m, /* serialization= */ NULL, /* fds= */ NULL, root);
         if (r < 0)
                 return r;
 
index 43bfbcbc8c4eaa35bb8f6b04d3c7ae7f550ec42f..b547ca6b8db48db4a4ee8d742fcd1f4e491e7f7c 100644 (file)
@@ -7,4 +7,4 @@
 #include "path-lookup.h"
 
 int verify_executable(Unit *u, const ExecCommand *exec);
-int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run_generators);
+int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run_generators, const char *root);
index 970ed34f06759a32b85654be791467942d8005ec..f5ce2c3ad3012c2fa61f7c8f149ae923eab3b14b 100644 (file)
@@ -2142,7 +2142,7 @@ 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);
+        return verify_units(strv_skip(argv, 1), arg_scope, arg_man, arg_generators, arg_root);
 }
 
 static int do_security(int argc, char *argv[], void *userdata) {
@@ -2381,9 +2381,9 @@ static int parse_argv(int argc, char *argv[]) {
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "Option --user is not supported for cat-config right now.");
 
-        if (arg_root && !streq_ptr(argv[optind], "cat-config"))
+        if (arg_root && !STRPTR_IN_SET(argv[optind], "cat-config", "verify"))
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "Option --root is only supported for cat-config right now.");
+                                       "Option --root is only supported for cat-config and verify right now.");
 
         return 1; /* work to do */
 }
index eb24245fb353281ae6e7f6f400e237f6de76c010..0914f92a2e0b09d4c5d308a67e831596f5860e16 100644 (file)
@@ -2908,7 +2908,7 @@ int main(int argc, char *argv[]) {
 
         before_startup = now(CLOCK_MONOTONIC);
 
-        r = manager_startup(m, arg_serialization, fds);
+        r = manager_startup(m, arg_serialization, fds, /* root= */ NULL);
         if (r < 0) {
                 error_message = "Failed to start up manager";
                 goto finish;
index 24dfe9fc06b831f2ed7d1cf5fe557a45b9a65cf1..aab230e1143026f9dd740ff7a16034b1a6b623eb 100644 (file)
@@ -1727,7 +1727,7 @@ void manager_reloading_stopp(Manager **m) {
         }
 }
 
-int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
+int manager_startup(Manager *m, FILE *serialization, FDSet *fds, const char *root) {
         int r;
 
         assert(m);
@@ -1736,7 +1736,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
          * but we should not touch the real generator directories. */
         r = lookup_paths_init(&m->lookup_paths, m->unit_file_scope,
                               MANAGER_IS_TEST_RUN(m) ? LOOKUP_PATHS_TEMPORARY_GENERATED : 0,
-                              NULL);
+                              root);
         if (r < 0)
                 return log_error_errno(r, "Failed to initialize path lookup table: %m");
 
index 284ea42a9dd43a5b989ac91131d942784f48a490..4ce43684746f5efe6966e937b299a8b6ce729a03 100644 (file)
@@ -470,7 +470,7 @@ int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager
 Manager* manager_free(Manager *m);
 DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
 
-int manager_startup(Manager *m, FILE *serialization, FDSet *fds);
+int manager_startup(Manager *m, FILE *serialization, FDSet *fds, const char *root);
 
 Job *manager_get_job(Manager *m, uint32_t id);
 Unit *manager_get_unit(Manager *m, const char *name);
index b29c0d78440f0572c459870e4b9a2acb3ea639d6..8b7d46bee3f8d4b9aead3c77c5d8a551cde55439 100644 (file)
@@ -97,7 +97,7 @@ int main(int argc, char *argv[]) {
         /* The simple tests succeeded. Now let's try full unit-based use-case. */
 
         assert_se(manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m) >= 0);
-        assert_se(manager_startup(m, NULL, NULL) >= 0);
+        assert_se(manager_startup(m, NULL, NULL, NULL) >= 0);
 
         assert_se(u = unit_new(m, sizeof(Service)));
         assert_se(unit_add_name(u, "foo.service") == 0);
index a6f8eb6f4ac612f36193135b9ef9c9d221a05e47..bbf3916872228000c0180f72927c87d82704656f 100644 (file)
@@ -304,7 +304,7 @@ int main(int argc, char *argv[]) {
         assert_se(runtime_dir = setup_fake_runtime_dir());
 
         assert_se(manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m) >= 0);
-        assert_se(manager_startup(m, NULL, NULL) >= 0);
+        assert_se(manager_startup(m, NULL, NULL, NULL) >= 0);
 
         assert_se(test_bpf_cgroup_programs(m,
                                 "single_prog.service", single_prog, ELEMENTSOF(single_prog)) >= 0);
index 19e159b9ff1c892105576a33732a962f46df7804..184b393dd51d36df04464075fdb067909a9d925e 100644 (file)
@@ -60,7 +60,7 @@ static int test_cgroup_mask(void) {
                 m->default_tasks_accounting = false;
         m->default_tasks_max = TASKS_MAX_UNSET;
 
-        assert_se(manager_startup(m, NULL, NULL) >= 0);
+        assert_se(manager_startup(m, NULL, NULL, NULL) >= 0);
 
         /* Load units and verify hierarchy. */
         assert_se(manager_load_startable_unit_or_warn(m, "parent.slice", NULL, &parent) >= 0);
index 225d138e41563e281400a0c0a079fb4e0c7d2b43..0fae2f64cb2abc5843676e75fd434cf3a2e101e9 100644 (file)
@@ -33,7 +33,7 @@ static int test_default_memory_low(void) {
         }
 
         assert_se(r >= 0);
-        assert_se(manager_startup(m, NULL, NULL) >= 0);
+        assert_se(manager_startup(m, NULL, NULL, NULL) >= 0);
 
         /* dml.slice has DefaultMemoryLow=50. Beyond that, individual subhierarchies look like this:
          *
index 6dc16193d3768fb79ab0cb5b9721f9bf94c54dcb..880af36fb5237cfa578d8cccb570be61630f8c58 100644 (file)
@@ -95,7 +95,7 @@ int main(int argc, char *argv[]) {
         if (manager_errno_skip_test(r))
                 return log_tests_skipped_errno(r, "manager_new");
         assert_se(r >= 0);
-        assert_se(manager_startup(m, NULL, NULL) >= 0);
+        assert_se(manager_startup(m, NULL, NULL, NULL) >= 0);
 
         printf("Load1:\n");
         assert_se(manager_load_startable_unit_or_warn(m, "a.service", NULL, &a) >= 0);
index 125e0bbf4f75c781ae5aaaef7dfe3826558879f7..a0481f119440fc0a53c38a907629aa0d62f9961a 100644 (file)
@@ -844,7 +844,7 @@ static int run_tests(UnitFileScope scope, const test_entry tests[], char **patte
         if (manager_errno_skip_test(r))
                 return log_tests_skipped_errno(r, "manager_new");
         assert_se(r >= 0);
-        assert_se(manager_startup(m, NULL, NULL) >= 0);
+        assert_se(manager_startup(m, NULL, NULL, NULL) >= 0);
 
         for (const test_entry *test = tests; test->f; test++)
                 if (strv_fnmatch_or_empty(patterns, test->name, FNM_NOESCAPE))
index b41a8abf7bc552741a938ea3a484512af0315e6a..e0ba99199c9dca5b78e9df93067de97baeb23d72 100644 (file)
@@ -104,7 +104,7 @@ static void test_config_parse_exec(void) {
         }
 
         assert_se(r >= 0);
-        assert_se(manager_startup(m, NULL, NULL) >= 0);
+        assert_se(manager_startup(m, NULL, NULL, NULL) >= 0);
 
         assert_se(u = unit_new(m, sizeof(Service)));
 
@@ -448,7 +448,7 @@ static void test_config_parse_log_extra_fields(void) {
         }
 
         assert_se(r >= 0);
-        assert_se(manager_startup(m, NULL, NULL) >= 0);
+        assert_se(manager_startup(m, NULL, NULL, NULL) >= 0);
 
         assert_se(u = unit_new(m, sizeof(Service)));
 
index 490fb136a7604b6185371f36587297a87d9390e0..04cb4fa37c710363615023ea33057ec982c0cc73 100644 (file)
@@ -38,7 +38,7 @@ static int setup_test(Manager **m) {
         if (manager_errno_skip_test(r))
                 return log_tests_skipped_errno(r, "manager_new");
         assert_se(r >= 0);
-        assert_se(manager_startup(tmp, NULL, NULL) >= 0);
+        assert_se(manager_startup(tmp, NULL, NULL, NULL) >= 0);
 
         STRV_FOREACH(test_path, tests_path) {
                 _cleanup_free_ char *p = NULL;
index 1f125b1d1e23035b0d90921a187923961e25cfa9..35f7be491ab973001b5393af2a1fd06daa988285 100644 (file)
@@ -34,7 +34,7 @@ int main(int argc, char *argv[]) {
         if (manager_errno_skip_test(r))
                 return log_tests_skipped_errno(r, "manager_new");
         assert_se(r >= 0);
-        assert_se(manager_startup(m, NULL, NULL) >= 0);
+        assert_se(manager_startup(m, NULL, NULL, NULL) >= 0);
 
         /* load idle ok */
         assert_se(manager_load_startable_unit_or_warn(m, "sched_idle_ok.service", NULL, &idle_ok) >= 0);
index 989172eee3b9569686ff5dc9c5df9b206e2dc557..ecad86baebff0738463de64e45b7c6af69251b1b 100644 (file)
@@ -138,7 +138,7 @@ int main(int argc, char *argv[]) {
         assert_se(runtime_dir = setup_fake_runtime_dir());
 
         assert_se(manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m) >= 0);
-        assert_se(manager_startup(m, NULL, NULL) >= 0);
+        assert_se(manager_startup(m, NULL, NULL, NULL) >= 0);
 
         assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "2000", STRV_MAKE("2000"), STRV_MAKE("any")) >= 0);
         assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "2000", STRV_MAKE("ipv6:2001-2002"), STRV_MAKE("any")) >= 0);
index 4afc46f10f04a58e55a7d0800b5454662f83753d..885ed802d40d65b72939805fd99734896a45e7f9 100644 (file)
@@ -27,7 +27,7 @@ int main(int argc, char *argv[]) {
         assert_se(runtime_dir = setup_fake_runtime_dir());
 
         assert_se(manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m) >= 0);
-        assert_se(manager_startup(m, NULL, NULL) >= 0);
+        assert_se(manager_startup(m, NULL, NULL, NULL) >= 0);
 
         assert_se(a = unit_new(m, sizeof(Service)));
         assert_se(unit_add_name(a, "a.service") >= 0);