diff --git a/man/systemd.xml b/man/systemd.xml index b409ba7c015..65c7fc2bb12 100644 --- a/man/systemd.xml +++ b/man/systemd.xml @@ -749,15 +749,18 @@ SIGRTMIN+22 + + Sets the service manager's log level to debug, in a fashion equivalent to + systemd.log_level=debug on the kernel command line. + + + SIGRTMIN+23 - Sets the log level to debug - (or info on - SIGRTMIN+23), as controlled via - systemd.log_level=debug (or - systemd.log_level=info on - SIGRTMIN+23) on the kernel command - line. + Restores the log level to its configured value. The configured value is derived from – in order + of priority – the value specified with systemd.log-level= on the kernel command line, or the + value specified with in the configuration file, or the built-in default of + info. @@ -769,20 +772,21 @@ SIGRTMIN+26 + + Restores the log target to its configured value. The configured value is derived from – in + order of priority – the value specified with systemd.log-target= on the kernel command line, + or the value specified with in the configuration file, or the built-in + default. + + + SIGRTMIN+27 SIGRTMIN+28 - Sets the log target to - journal-or-kmsg (or - console on - SIGRTMIN+27, kmsg on - SIGRTMIN+28), as controlled via - systemd.log_target=journal-or-kmsg (or - systemd.log_target=console on - SIGRTMIN+27 or - systemd.log_target=kmsg on - SIGRTMIN+28) on the kernel command - line. + Sets the log target to console on SIGRTMIN+27 (or + kmsg on SIGRTMIN+28), in a fashion equivalent to + systemd.log_target=console (or systemd.log_target=kmsg on + SIGRTMIN+28) on the kernel command line. diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 09daf268b7f..016741e40b5 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -114,6 +114,7 @@ static int property_set_log_target( void *userdata, sd_bus_error *error) { + Manager *m = userdata; const char *t; int r; @@ -124,7 +125,19 @@ static int property_set_log_target( if (r < 0) return r; - return log_set_target_from_string(t); + if (isempty(t)) + manager_restore_original_log_target(m); + else { + LogTarget target; + + target = log_target_from_string(t); + if (target < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid log target '%s'", t); + + manager_override_log_target(m, target); + } + + return 0; } static int property_get_log_level( @@ -158,6 +171,7 @@ static int property_set_log_level( void *userdata, sd_bus_error *error) { + Manager *m = userdata; const char *t; int r; @@ -168,10 +182,19 @@ static int property_set_log_level( if (r < 0) return r; - r = log_set_max_level_from_string(t); - if (r == 0) - log_info("Setting log level to %s.", t); - return r; + if (isempty(t)) + manager_restore_original_log_level(m); + else { + int level; + + level = log_level_from_string(t); + if (level < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid log level '%s'", t); + + manager_override_log_level(m, level); + } + + return 0; } static int property_get_progress( diff --git a/src/core/main.c b/src/core/main.c index 1e75ad7203d..f396a61e124 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -525,10 +525,10 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat return 0; \ } -DEFINE_SETTER(config_parse_level2, log_set_max_level_from_string, "log level") -DEFINE_SETTER(config_parse_target, log_set_target_from_string, "target") -DEFINE_SETTER(config_parse_color, log_show_color_from_string, "color" ) -DEFINE_SETTER(config_parse_location, log_show_location_from_string, "location") +DEFINE_SETTER(config_parse_level2, log_set_max_level_from_string, "log level"); +DEFINE_SETTER(config_parse_target, log_set_target_from_string, "target"); +DEFINE_SETTER(config_parse_color, log_show_color_from_string, "color" ); +DEFINE_SETTER(config_parse_location, log_show_location_from_string, "location"); static int config_parse_cpu_affinity2( const char *unit, @@ -1640,20 +1640,35 @@ static int invoke_main_loop( switch (m->exit_code) { - case MANAGER_RELOAD: + case MANAGER_RELOAD: { + LogTarget saved_log_target; + int saved_log_level; + log_info("Reloading."); + /* First, save any overriden log level/target, then parse the configuration file, which might + * change the log level to new settings. */ + + saved_log_level = m->log_level_overridden ? log_get_max_level() : -1; + saved_log_target = m->log_target_overridden ? log_get_target() : _LOG_TARGET_INVALID; + r = parse_config_file(); if (r < 0) log_warning_errno(r, "Failed to parse config file, ignoring: %m"); set_manager_defaults(m); + if (saved_log_level >= 0) + manager_override_log_level(m, saved_log_level); + if (saved_log_target >= 0) + manager_override_log_target(m, saved_log_target); + r = manager_reload(m); if (r < 0) log_warning_errno(r, "Failed to reload, ignoring: %m"); break; + } case MANAGER_REEXECUTE: @@ -2173,6 +2188,9 @@ int main(int argc, char *argv[]) { log_set_upgrade_syslog_to_journal(true); if (getpid_cached() == 1) { + /* When we run as PID 1 force system mode */ + arg_system = true; + /* Disable the umask logic */ umask(0); @@ -2189,7 +2207,6 @@ int main(int argc, char *argv[]) { if (detect_container() <= 0) { /* Running outside of a container as PID 1 */ - arg_system = true; log_set_target(LOG_TARGET_KMSG); log_open(); @@ -2228,7 +2245,6 @@ int main(int argc, char *argv[]) { } else { /* Running inside a container, as PID 1 */ - arg_system = true; log_set_target(LOG_TARGET_CONSOLE); log_open(); diff --git a/src/core/manager.c b/src/core/manager.c index e1ce9229a32..a6b2edcb83f 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -74,6 +74,7 @@ #include "string-util.h" #include "strv.h" #include "strxcpyx.h" +#include "syslog-util.h" #include "terminal-util.h" #include "time-util.h" #include "transaction.h" @@ -735,6 +736,8 @@ int manager_new(UnitFileScope scope, unsigned test_run_flags, Manager **_m) { m->default_timeout_start_usec = DEFAULT_TIMEOUT_USEC; m->default_timeout_stop_usec = DEFAULT_TIMEOUT_USEC; m->default_restart_usec = DEFAULT_RESTART_USEC; + m->original_log_level = -1; + m->original_log_target = _LOG_TARGET_INVALID; #if ENABLE_EFI if (MANAGER_IS_SYSTEM(m) && detect_container() <= 0) @@ -2626,13 +2629,11 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t break; case 22: - log_set_max_level(LOG_DEBUG); - log_info("Setting log level to debug."); + manager_override_log_level(m, LOG_DEBUG); break; case 23: - log_set_max_level(LOG_INFO); - log_info("Setting log level to info."); + manager_restore_original_log_level(m); break; case 24: @@ -2646,18 +2647,15 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t case 26: case 29: /* compatibility: used to be mapped to LOG_TARGET_SYSLOG_OR_KMSG */ - log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); - log_notice("Setting log target to journal-or-kmsg."); + manager_restore_original_log_target(m); break; case 27: - log_set_target(LOG_TARGET_CONSOLE); - log_notice("Setting log target to console."); + manager_override_log_target(m, LOG_TARGET_CONSOLE); break; case 28: - log_set_target(LOG_TARGET_KMSG); - log_notice("Setting log target to kmsg."); + manager_override_log_target(m, LOG_TARGET_KMSG); break; default: @@ -3027,6 +3025,11 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { fprintf(f, "taint-logged=%s\n", yes_no(m->taint_logged)); fprintf(f, "service-watchdogs=%s\n", yes_no(m->service_watchdogs)); + if (m->log_level_overridden) + fprintf(f, "log-level-override=%i\n", log_get_max_level()); + if (m->log_target_overridden) + fprintf(f, "log-target-override=%s\n", log_target_to_string(log_get_target())); + for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) { /* The userspace and finish timestamps only apply to the host system, hence only serialize them there */ if (in_initrd() && IN_SET(q, MANAGER_TIMESTAMP_USERSPACE, MANAGER_TIMESTAMP_FINISH)) @@ -3210,6 +3213,24 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { else m->service_watchdogs = b; + } else if ((val = startswith(l, "log-level-override="))) { + int level; + + level = log_level_from_string(val); + if (level < 0) + log_notice("Failed to parse log-level-override value '%s', ignoring.", val); + else + manager_override_log_level(m, level); + + } else if ((val = startswith(l, "log-target-override="))) { + LogTarget target; + + target = log_target_from_string(val); + if (target < 0) + log_notice("Failed to parse log-target-override value '%s', ignoring.", val); + else + manager_override_log_target(m, target); + } else if (startswith(l, "env=")) { r = deserialize_environment(&m->environment, l); if (r == -ENOMEM) @@ -4448,6 +4469,59 @@ void manager_unref_console(Manager *m) { m->no_console_output = false; /* unset no_console_output flag, since the console is definitely free now */ } +void manager_override_log_level(Manager *m, int level) { + _cleanup_free_ char *s = NULL; + assert(m); + + if (!m->log_level_overridden) { + m->original_log_level = log_get_max_level(); + m->log_level_overridden = true; + } + + (void) log_level_to_string_alloc(level, &s); + log_info("Setting log level to %s.", strna(s)); + + log_set_max_level(level); +} + +void manager_restore_original_log_level(Manager *m) { + _cleanup_free_ char *s = NULL; + assert(m); + + if (!m->log_level_overridden) + return; + + (void) log_level_to_string_alloc(m->original_log_level, &s); + log_info("Restoring log level to original (%s).", strna(s)); + + log_set_max_level(m->original_log_level); + m->log_level_overridden = false; +} + +void manager_override_log_target(Manager *m, LogTarget target) { + assert(m); + + if (!m->log_target_overridden) { + m->original_log_target = log_get_target(); + m->log_target_overridden = true; + } + + log_info("Setting log target to %s.", log_target_to_string(target)); + log_set_target(target); +} + +void manager_restore_original_log_target(Manager *m) { + assert(m); + + if (!m->log_target_overridden) + return; + + log_info("Restoring log target to original %s.", log_target_to_string(m->original_log_target)); + + log_set_target(m->original_log_target); + m->log_target_overridden = false; +} + static const char *const manager_state_table[_MANAGER_STATE_MAX] = { [MANAGER_INITIALIZING] = "initializing", [MANAGER_STARTING] = "starting", diff --git a/src/core/manager.h b/src/core/manager.h index 8868e9c158c..4555a4ff152 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -302,6 +302,11 @@ struct Manager { uint64_t default_tasks_max; usec_t default_timer_accuracy_usec; + int original_log_level; + LogTarget original_log_target; + bool log_level_overridden:1; + bool log_target_overridden:1; + struct rlimit *rlimit[_RLIMIT_MAX]; /* non-zero if we are reloading or reexecuting, */ @@ -465,6 +470,12 @@ char *manager_taint_string(Manager *m); void manager_ref_console(Manager *m); void manager_unref_console(Manager *m); +void manager_override_log_level(Manager *m, int level); +void manager_restore_original_log_level(Manager *m); + +void manager_override_log_target(Manager *m, LogTarget target); +void manager_restore_original_log_target(Manager *m); + const char *manager_state_to_string(ManagerState m) _const_; ManagerState manager_state_from_string(const char *s) _pure_;