diff options
-rw-r--r-- | man/systemd-analyze.xml | 30 | ||||
-rw-r--r-- | src/analyze/analyze.c | 27 | ||||
-rw-r--r-- | src/basic/conf-files.c | 32 | ||||
-rw-r--r-- | src/basic/conf-files.h | 1 | ||||
-rw-r--r-- | src/basic/terminal-util.c | 9 | ||||
-rw-r--r-- | src/basic/terminal-util.h | 7 | ||||
-rw-r--r-- | src/systemctl/systemctl.c | 2 | ||||
-rw-r--r-- | src/test/test-terminal-util.c | 5 |
8 files changed, 107 insertions, 6 deletions
diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml index de14a7e3ce..70f87f4786 100644 --- a/man/systemd-analyze.xml +++ b/man/systemd-analyze.xml @@ -81,6 +81,12 @@ <cmdsynopsis> <command>systemd-analyze</command> <arg choice="opt" rep="repeat">OPTIONS</arg> + <arg choice="plain">cat-config</arg> + <arg choice="plain" rep="repeat"><replaceable>NAME</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>systemd-analyze</command> + <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="plain">unit-paths</arg> </cmdsynopsis> <cmdsynopsis> @@ -180,6 +186,30 @@ state. Its format is subject to change without notice and should not be parsed by applications.</para> + <para><command>systemd-analyze cat-config</command> is similar + to <command>systemctl cat</command>, but operates on config files. + It will copy the contents of a config file and any drop-ins to standard + output, using the usual systemd set of directories and rules for + precedence.</para> + + <example> + <title>Showing logind configuration</title> + <programlisting>$ systemd-analyze cat-config systemd/logind.conf +# /etc/systemd/logind.conf +# This file is part of systemd. +... +[Login] +NAutoVTs=8 +... + +# /usr/lib/systemd/logind.conf.d/20-test.conf +... some override from another package + +# /etc/systemd/logind.conf.d/50-override.conf +... some adminstrator override + </programlisting> + </example> + <para><command>systemd-analyze unit-paths</command> outputs a list of all directories from which unit files, <filename>.d</filename> overrides, and <filename>.wants</filename>, <filename>.requires</filename> symlinks may be diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 06add1171d..0b0925d18c 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -19,12 +19,14 @@ #include "bus-unit-util.h" #include "bus-util.h" #include "calendarspec.h" +#include "conf-files.h" #include "glob-util.h" #include "hashmap.h" #include "locale-util.h" #include "log.h" #include "pager.h" #include "parse-util.h" +#include "path-util.h" #if HAVE_SECCOMP #include "seccomp-util.h" #endif @@ -1312,6 +1314,29 @@ static int dump(int argc, char *argv[], void *userdata) { return 0; } +static int cat_config(int argc, char *argv[], void *userdata) { + char **arg; + int r; + + (void) pager_open(arg_no_pager, false); + + STRV_FOREACH(arg, argv + 1) { + if (arg != argv + 1) + puts(""); + + if (path_is_absolute(*arg)) { + log_error("Arguments must be config file names (relative to /etc/"); + return -EINVAL; + } + + r = conf_files_cat(*arg); + if (r < 0) + return r; + } + + return 0; +} + static int set_log_level(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; @@ -1643,6 +1668,7 @@ static int help(int argc, char *argv[], void *userdata) { " log-level [LEVEL] Get/set logging threshold for manager\n" " log-target [TARGET] Get/set logging target for manager\n" " dump Output state serialization of service manager\n" + " cat-config Show configuration file and drop-ins\n" " unit-paths List load directories for units\n" " syscall-filter [NAME...] Print list of syscalls in seccomp filter\n" " verify FILE... Check unit files for correctness\n" @@ -1819,6 +1845,7 @@ int main(int argc, char *argv[]) { { "set-log-target", 2, 2, 0, set_log_target }, { "get-log-target", VERB_ANY, 1, 0, get_log_target }, { "dump", VERB_ANY, 1, 0, dump }, + { "cat-config", 2, VERB_ANY, 0, cat_config }, { "unit-paths", 1, 1, 0, dump_unit_paths }, { "syscall-filter", VERB_ANY, VERB_ANY, 0, dump_syscall_filters }, { "verify", 2, VERB_ANY, 0, do_verify }, diff --git a/src/basic/conf-files.c b/src/basic/conf-files.c index 8e0fb06ad9..4c5ecb5cbb 100644 --- a/src/basic/conf-files.c +++ b/src/basic/conf-files.c @@ -13,6 +13,7 @@ #include <string.h> #include "conf-files.h" +#include "def.h" #include "dirent-util.h" #include "fd-util.h" #include "hashmap.h" @@ -23,6 +24,7 @@ #include "stat-util.h" #include "string-util.h" #include "strv.h" +#include "terminal-util.h" #include "util.h" static int files_add(Hashmap *h, const char *suffix, const char *root, unsigned flags, const char *path) { @@ -256,3 +258,33 @@ int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, u return conf_files_list_strv_internal(strv, suffix, root, flags, d); } + +int conf_files_cat(const char *name) { + _cleanup_strv_free_ char **dirs = NULL, **files = NULL; + const char *dir; + char **t; + int r; + + NULSTR_FOREACH(dir, CONF_PATHS_NULSTR("")) { + assert(endswith(dir, "/")); + r = strv_extendf(&dirs, "%s%s.d", dir, name); + if (r < 0) + return log_error("Failed to build directory list: %m"); + } + + r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char* const*) dirs); + if (r < 0) + return log_error_errno(r, "Failed to query file list: %m"); + + name = strjoina("/etc/", name); + + if (DEBUG_LOGGING) { + log_debug("Looking for configuration in:"); + log_debug(" %s", name); + STRV_FOREACH(t, dirs) + log_debug(" %s/*.conf", *t); + } + + /* show */ + return cat_files(name, files, CAT_FLAGS_MAIN_FILE_OPTIONAL); +} diff --git a/src/basic/conf-files.h b/src/basic/conf-files.h index b902c3a3b3..3d1feadf03 100644 --- a/src/basic/conf-files.h +++ b/src/basic/conf-files.h @@ -17,3 +17,4 @@ int conf_files_list_strv(char ***ret, const char *suffix, const char *root, unsi int conf_files_list_nulstr(char ***ret, const char *suffix, const char *root, unsigned flags, const char *dirs); int conf_files_insert(char ***strv, const char *root, char **dirs, const char *path); int conf_files_insert_nulstr(char ***strv, const char *root, const char *dirs, const char *path); +int conf_files_cat(const char *name); diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index 5624c03bce..c2b7cd799e 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -1381,13 +1381,18 @@ static int cat_file(const char *filename, bool newline) { return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, 0); } -int cat_files(const char *file, char **dropins) { +int cat_files(const char *file, char **dropins, CatFlags flags) { char **path; int r; if (file) { r = cat_file(file, false); - if (r < 0) + if (r == -ENOENT && (flags & CAT_FLAGS_MAIN_FILE_OPTIONAL)) + printf("%s# config file %s not found%s\n", + ansi_highlight_magenta(), + file, + ansi_normal()); + else if (r < 0) return log_warning_errno(r, "Failed to cat %s: %m", file); } diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h index d2d3ad5127..ea7eb2d63b 100644 --- a/src/basic/terminal-util.h +++ b/src/basic/terminal-util.h @@ -133,6 +133,7 @@ DEFINE_ANSI_FUNC(highlight_red, HIGHLIGHT_RED); DEFINE_ANSI_FUNC(highlight_green, HIGHLIGHT_GREEN); DEFINE_ANSI_FUNC(highlight_yellow, HIGHLIGHT_YELLOW); DEFINE_ANSI_FUNC(highlight_blue, HIGHLIGHT_BLUE); +DEFINE_ANSI_FUNC(highlight_magenta, HIGHLIGHT_MAGENTA); DEFINE_ANSI_FUNC(normal, NORMAL); DEFINE_ANSI_FUNC_UNDERLINE(underline, UNDERLINE, NORMAL); @@ -160,4 +161,8 @@ int vt_reset_keyboard(int fd); int terminal_urlify(const char *url, const char *text, char **ret); int terminal_urlify_path(const char *path, const char *text, char **ret); -int cat_files(const char *file, char **files); +typedef enum CatFlags { + CAT_FLAGS_MAIN_FILE_OPTIONAL = 1 << 1, +} CatFlags; + +int cat_files(const char *file, char **dropins, CatFlags flags); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 23ce6acd6a..a1938bc91b 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -5376,7 +5376,7 @@ static int cat(int argc, char *argv[], void *userdata) { arg_scope == UNIT_FILE_SYSTEM ? "" : " --user", ansi_normal()); - r = cat_files(fragment_path, dropin_paths); + r = cat_files(fragment_path, dropin_paths, 0); if (r < 0) return r; } diff --git a/src/test/test-terminal-util.c b/src/test/test-terminal-util.c index 92add77531..61a3ea5e56 100644 --- a/src/test/test-terminal-util.c +++ b/src/test/test-terminal-util.c @@ -78,10 +78,11 @@ static void test_terminal_urlify(void) { } static void test_cat_files(void) { - assert_se(cat_files("/no/such/file", NULL) == -ENOENT); + assert_se(cat_files("/no/such/file", NULL, 0) == -ENOENT); + assert_se(cat_files("/no/such/file", NULL, CAT_FLAGS_MAIN_FILE_OPTIONAL) == 0); if (access("/etc/fstab", R_OK) >= 0) - assert_se(cat_files("/etc/fstab", STRV_MAKE("/etc/fstab", "/etc/fstab")) == 0); + assert_se(cat_files("/etc/fstab", STRV_MAKE("/etc/fstab", "/etc/fstab"), 0) == 0); } int main(int argc, char *argv[]) { |