mirror of
https://github.com/systemd/systemd.git
synced 2024-11-23 18:23:32 +08:00
pid1: preserve current value of log level across re-{load,execution}
To make debugging easier, this patches allows one to change the log level and do reload/reexec without modifying configuration permanently, which makes debugging easier. Indeed if one changed the log max level at runtime (via the bus or via signals), the change was lost on the next daemon reload/reexecution. In order to restore the original value back (set via system.conf, environment variables or any other means), the empty string in the "LogLevel" property is now supported as well as sending SIGRTMIN+23 signal.
This commit is contained in:
parent
6f8a8b84f2
commit
a6ecbf836c
@ -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>
|
||||
|
@ -158,6 +158,7 @@ static int property_set_log_level(
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Manager *m = userdata;
|
||||
const char *t;
|
||||
int r;
|
||||
|
||||
@ -168,10 +169,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,28 @@ static int invoke_main_loop(
|
||||
|
||||
switch (m->exit_code) {
|
||||
|
||||
case MANAGER_RELOAD:
|
||||
case MANAGER_RELOAD: {
|
||||
int saved_log_level;
|
||||
|
||||
log_info("Reloading.");
|
||||
|
||||
saved_log_level = m->log_level_overridden ? log_get_max_level() : -1;
|
||||
|
||||
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);
|
||||
|
||||
r = manager_reload(m);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to reload, ignoring: %m");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MANAGER_REEXECUTE:
|
||||
|
||||
|
@ -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,7 @@ 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;
|
||||
|
||||
#if ENABLE_EFI
|
||||
if (MANAGER_IS_SYSTEM(m) && detect_container() <= 0)
|
||||
@ -2626,13 +2628,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:
|
||||
@ -3027,6 +3027,9 @@ 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());
|
||||
|
||||
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,15 @@ 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 (startswith(l, "env=")) {
|
||||
r = deserialize_environment(&m->environment, l);
|
||||
if (r == -ENOMEM)
|
||||
@ -4448,6 +4460,35 @@ 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;
|
||||
}
|
||||
|
||||
static const char *const manager_state_table[_MANAGER_STATE_MAX] = {
|
||||
[MANAGER_INITIALIZING] = "initializing",
|
||||
[MANAGER_STARTING] = "starting",
|
||||
|
@ -302,6 +302,9 @@ struct Manager {
|
||||
uint64_t default_tasks_max;
|
||||
usec_t default_timer_accuracy_usec;
|
||||
|
||||
int original_log_level;
|
||||
bool log_level_overridden:1;
|
||||
|
||||
struct rlimit *rlimit[_RLIMIT_MAX];
|
||||
|
||||
/* non-zero if we are reloading or reexecuting, */
|
||||
@ -465,6 +468,9 @@ 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);
|
||||
|
||||
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