diff options
-rw-r--r-- | man/systemd.xml | 14 | ||||
-rw-r--r-- | src/core/main.c | 36 | ||||
-rw-r--r-- | src/core/manager.c | 21 | ||||
-rw-r--r-- | src/core/manager.h | 5 | ||||
-rw-r--r-- | src/shared/conf-parser.c | 29 | ||||
-rw-r--r-- | src/shared/conf-parser.h | 1 | ||||
-rw-r--r-- | src/shared/exit-status.c | 17 | ||||
-rw-r--r-- | src/shared/exit-status.h | 12 |
8 files changed, 106 insertions, 29 deletions
diff --git a/man/systemd.xml b/man/systemd.xml index acba820fdf..4e35c9695b 100644 --- a/man/systemd.xml +++ b/man/systemd.xml @@ -1061,14 +1061,20 @@ <term><varname>systemd.show_status=</varname></term> <listitem><para>Takes a boolean - argument. If <option>true</option>, - shows terse service status updates on - the console during bootup. Defaults to + argument or the constant + <constant>auto</constant>. If + <option>true</option>, shows terse + service status updates on the console + during bootup. + <constant>auto</constant> behaves like + <option>false</option> until a service + fails or there is a significant delay + in boot. Defaults to <option>true</option>, unless <option>quiet</option> is passed as kernel command line option in which case it defaults to - <option>false</option>.</para></listitem> + <constant>auto</constant>.</para></listitem> </varlistentry> <varlistentry> diff --git a/src/core/main.c b/src/core/main.c index fb34e4d3d1..404fee7b2e 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -90,7 +90,7 @@ static bool arg_dump_core = true; static bool arg_crash_shell = false; static int arg_crash_chvt = -1; static bool arg_confirm_spawn = false; -static bool arg_show_status = true; +static ShowStatus arg_show_status = SHOW_STATUS_UNSET; static bool arg_switched_root = false; static char ***arg_join_controllers = NULL; static ExecOutput arg_default_std_output = EXEC_OUTPUT_JOURNAL; @@ -338,10 +338,9 @@ static int parse_proc_cmdline_word(const char *word) { } else if (startswith(word, "systemd.show_status=")) { int r; - if ((r = parse_boolean(word + 20)) < 0) + r = parse_show_status(word + 20, &arg_show_status); + if (r < 0) log_warning("Failed to parse show status switch %s. Ignoring.", word + 20); - else - arg_show_status = r; } else if (startswith(word, "systemd.default_standard_output=")) { int r; @@ -396,7 +395,7 @@ static int parse_proc_cmdline_word(const char *word) { "systemd.crash_shell=0|1 Run shell on crash\n" "systemd.crash_chvt=N Change to VT #N on crash\n" "systemd.confirm_spawn=0|1 Confirm every process spawn\n" - "systemd.show_status=0|1 Show status updates on the console during bootup\n" + "systemd.show_status=0|1|auto Show status updates on the console during bootup\n" "systemd.log_target=console|kmsg|journal|journal-or-kmsg|syslog|syslog-or-kmsg|null\n" " Log target\n" "systemd.log_level=LEVEL Log level\n" @@ -409,9 +408,10 @@ static int parse_proc_cmdline_word(const char *word) { "systemd.setenv=ASSIGNMENT Set an environment variable for all spawned processes\n"); } - } else if (streq(word, "quiet")) - arg_show_status = false; - else if (streq(word, "debug")) { + } else if (streq(word, "quiet")) { + if (arg_show_status == SHOW_STATUS_UNSET) + arg_show_status = SHOW_STATUS_AUTO; + } else if (streq(word, "debug")) { /* Log to kmsg, the journal socket will fill up before the * journal is started and tools running during that time * will block with every log message for for 60 seconds, @@ -638,7 +638,7 @@ static int parse_config_file(void) { { "Manager", "LogLocation", config_parse_location, 0, NULL }, { "Manager", "DumpCore", config_parse_bool, 0, &arg_dump_core }, { "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell }, - { "Manager", "ShowStatus", config_parse_bool, 0, &arg_show_status }, + { "Manager", "ShowStatus", config_parse_show_status, 0, &arg_show_status }, { "Manager", "CrashChVT", config_parse_int, 0, &arg_crash_chvt }, { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, NULL }, { "Manager", "DefaultStandardOutput", config_parse_output, 0, &arg_default_std_output }, @@ -897,12 +897,14 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_SHOW_STATUS: - r = optarg ? parse_boolean(optarg) : 1; - if (r < 0) { - log_error("Failed to parse show status boolean %s.", optarg); - return r; - } - arg_show_status = r; + if (optarg) { + r = parse_show_status(optarg, &arg_show_status); + if (r < 0) { + log_error("Failed to parse show status boolean %s.", optarg); + return r; + } + } else + arg_show_status = SHOW_STATUS_YES; break; case ARG_DESERIALIZE: { @@ -1482,7 +1484,7 @@ int main(int argc, char *argv[]) { } if (arg_running_as == SYSTEMD_SYSTEM && !skip_setup) { - if (arg_show_status || plymouth_running()) + if (arg_show_status > 0 || plymouth_running()) status_welcome(); #ifdef HAVE_KMOD @@ -1557,6 +1559,8 @@ int main(int argc, char *argv[]) { if (arg_default_environment) manager_environment_add(m, NULL, arg_default_environment); + if (arg_show_status == SHOW_STATUS_UNSET) + arg_show_status = SHOW_STATUS_YES; manager_set_show_status(m, arg_show_status); /* Remember whether we should queue the default job */ diff --git a/src/core/manager.c b/src/core/manager.c index 9ed802398b..9f615e64eb 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -102,7 +102,7 @@ static int manager_watch_jobs_in_progress(Manager *m) { if (m->jobs_in_progress_event_source) return 0; - return sd_event_add_monotonic(m->event, JOBS_IN_PROGRESS_WAIT_USEC, 0, manager_dispatch_jobs_in_progress, m, &m->jobs_in_progress_event_source); + return sd_event_add_monotonic(m->event, now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC, 0, manager_dispatch_jobs_in_progress, m, &m->jobs_in_progress_event_source); } #define CYLON_BUFFER_EXTRA (2*(sizeof(ANSI_RED_ON)-1) + sizeof(ANSI_HIGHLIGHT_RED_ON)-1 + 2*(sizeof(ANSI_HIGHLIGHT_OFF)-1)) @@ -148,6 +148,9 @@ static void manager_print_jobs_in_progress(Manager *m) { assert(m); + if (m->show_status == SHOW_STATUS_AUTO) + manager_set_show_status(m, SHOW_STATUS_TEMPORARY); + print_nr = (m->jobs_in_progress_iteration / JOBS_IN_PROGRESS_PERIOD_DIVISOR) % m->n_running_jobs; HASHMAP_FOREACH(j, m->jobs, i) @@ -1637,12 +1640,12 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t case 20: log_debug("Enabling showing of status."); - manager_set_show_status(m, true); + manager_set_show_status(m, SHOW_STATUS_YES); break; case 21: log_debug("Disabling showing of status."); - manager_set_show_status(m, false); + manager_set_show_status(m, SHOW_STATUS_NO); break; case 22: @@ -2456,6 +2459,9 @@ void manager_check_finished(Manager *m) { return; } + if (m->show_status == SHOW_STATUS_TEMPORARY) + manager_set_show_status(m, SHOW_STATUS_AUTO); + /* Notify Type=idle units that we are done now */ m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source); manager_close_idle_pipe(m); @@ -2754,15 +2760,16 @@ void manager_recheck_journal(Manager *m) { log_open(); } -void manager_set_show_status(Manager *m, bool b) { +void manager_set_show_status(Manager *m, ShowStatus mode) { assert(m); + assert(IN_SET(mode, SHOW_STATUS_AUTO, SHOW_STATUS_NO, SHOW_STATUS_YES, SHOW_STATUS_TEMPORARY)); if (m->running_as != SYSTEMD_SYSTEM) return; - m->show_status = b; + m->show_status = mode; - if (b) + if (mode > 0) touch("/run/systemd/show-status"); else unlink("/run/systemd/show-status"); @@ -2777,7 +2784,7 @@ static bool manager_get_show_status(Manager *m) { if (m->no_console_output) return false; - if (m->show_status) + if (m->show_status > 0) return true; /* If Plymouth is running make sure we show the status, so diff --git a/src/core/manager.h b/src/core/manager.h index fdf60ae696..3065822cfa 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -57,6 +57,7 @@ typedef enum ManagerExitCode { #include "path-lookup.h" #include "execute.h" #include "unit-name.h" +#include "exit-status.h" struct Manager { /* Note that the set of units we know of is allowed to be @@ -198,7 +199,7 @@ struct Manager { bool taint_usr:1; - bool show_status; + ShowStatus show_status; bool confirm_spawn; bool no_console_output; @@ -296,7 +297,7 @@ void manager_undo_generators(Manager *m); void manager_recheck_journal(Manager *m); -void manager_set_show_status(Manager *m, bool b); +void manager_set_show_status(Manager *m, ShowStatus mode); void manager_status_printf(Manager *m, bool ephemeral, const char *status, const char *format, ...) _printf_(4,5); Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path); diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index 1e3cee5beb..df4e961ea0 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -528,6 +528,35 @@ int config_parse_bool(const char* unit, return 0; } +int config_parse_show_status(const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + int k; + ShowStatus *b = data; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + k = parse_show_status(rvalue, b); + if (k < 0) { + log_syntax(unit, LOG_ERR, filename, line, -k, + "Failed to parse show status setting, ignoring: %s", rvalue); + return 0; + } + + return 0; +} + int config_parse_string(const char *unit, const char *filename, unsigned line, diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h index 2d5aa31c3b..ebbcaa54fe 100644 --- a/src/shared/conf-parser.h +++ b/src/shared/conf-parser.h @@ -100,6 +100,7 @@ int config_parse_double(const char *unit, const char *filename, unsigned line, c int config_parse_bytes_size(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bytes_off(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bool(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_show_status(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_string(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_path(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_strv(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); diff --git a/src/shared/exit-status.c b/src/shared/exit-status.c index 45131f2b2a..ef2d63f57d 100644 --- a/src/shared/exit-status.c +++ b/src/shared/exit-status.c @@ -190,3 +190,20 @@ bool is_clean_exit_lsb(int code, int status, ExitStatusSet *success_status) { code == CLD_EXITED && (status == EXIT_NOTINSTALLED || status == EXIT_NOTCONFIGURED); } + +int parse_show_status(const char *v, ShowStatus *ret) { + int r; + + assert(v); + assert(ret); + + if (streq(v, "auto")) { + *ret = SHOW_STATUS_AUTO; + return 0; + } + r = parse_boolean(v); + if (r < 0) + return r; + *ret = r ? SHOW_STATUS_YES : SHOW_STATUS_NO; + return 0; +} diff --git a/src/shared/exit-status.h b/src/shared/exit-status.h index 1f035a3007..1ecf9d5784 100644 --- a/src/shared/exit-status.h +++ b/src/shared/exit-status.h @@ -86,3 +86,15 @@ const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) _con bool is_clean_exit(int code, int status, ExitStatusSet *success_status); bool is_clean_exit_lsb(int code, int status, ExitStatusSet *success_status); + +/* Manager status */ + +typedef enum ShowStatus { + SHOW_STATUS_UNSET = -2, + SHOW_STATUS_AUTO = -1, + SHOW_STATUS_NO = 0, + SHOW_STATUS_YES = 1, + SHOW_STATUS_TEMPORARY = 2, +} ShowStatus; + +int parse_show_status(const char *v, ShowStatus *ret); |