mirror of
https://github.com/systemd/systemd.git
synced 2024-11-02 19:21:53 +03:00
Merge pull request #9263 from poettering/log-serialize
save/restore log level across daemon reexec
This commit is contained in:
commit
d122ed1ba8
@ -749,15 +749,18 @@
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>SIGRTMIN+22</constant></term>
|
||||
|
||||
<listitem><para>Sets the service manager's log level to <literal>debug</literal>, in a fashion equivalent to
|
||||
<varname>systemd.log_level=debug</varname> on the kernel command line.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>SIGRTMIN+23</constant></term>
|
||||
|
||||
<listitem><para>Sets the log level to <literal>debug</literal>
|
||||
(or <literal>info</literal> on
|
||||
<constant>SIGRTMIN+23</constant>), as controlled via
|
||||
<varname>systemd.log_level=debug</varname> (or
|
||||
<varname>systemd.log_level=info</varname> on
|
||||
<constant>SIGRTMIN+23</constant>) on the kernel command
|
||||
line.</para></listitem>
|
||||
<listitem><para>Restores the log level to its configured value. The configured value is derived from – in order
|
||||
of priority – the value specified with <varname>systemd.log-level=</varname> on the kernel command line, or the
|
||||
value specified with <option>LogLevel=</option> in the configuration file, or the built-in default of
|
||||
<literal>info</literal>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@ -769,20 +772,21 @@
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>SIGRTMIN+26</constant></term>
|
||||
|
||||
<listitem><para>Restores the log target to its configured value. The configured value is derived from – in
|
||||
order of priority – the value specified with <varname>systemd.log-target=</varname> on the kernel command line,
|
||||
or the value specified with <option>LogTarget=</option> in the configuration file, or the built-in
|
||||
default.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>SIGRTMIN+27</constant></term>
|
||||
<term><constant>SIGRTMIN+28</constant></term>
|
||||
|
||||
<listitem><para>Sets the log target to
|
||||
<literal>journal-or-kmsg</literal> (or
|
||||
<literal>console</literal> on
|
||||
<constant>SIGRTMIN+27</constant>, <literal>kmsg</literal> on
|
||||
<constant>SIGRTMIN+28</constant>), as controlled via
|
||||
<varname>systemd.log_target=journal-or-kmsg</varname> (or
|
||||
<varname>systemd.log_target=console</varname> on
|
||||
<constant>SIGRTMIN+27</constant> or
|
||||
<varname>systemd.log_target=kmsg</varname> on
|
||||
<constant>SIGRTMIN+28</constant>) on the kernel command
|
||||
line.</para></listitem>
|
||||
<listitem><para>Sets the log target to <literal>console</literal> on <constant>SIGRTMIN+27</constant> (or
|
||||
<literal>kmsg</literal> on <constant>SIGRTMIN+28</constant>), in a fashion equivalent to
|
||||
<varname>systemd.log_target=console</varname> (or <varname>systemd.log_target=kmsg</varname> on
|
||||
<constant>SIGRTMIN+28</constant>) on the kernel command line.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
@ -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(
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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_;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user