summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/systemd.xml14
-rw-r--r--src/core/main.c36
-rw-r--r--src/core/manager.c21
-rw-r--r--src/core/manager.h5
-rw-r--r--src/shared/conf-parser.c29
-rw-r--r--src/shared/conf-parser.h1
-rw-r--r--src/shared/exit-status.c17
-rw-r--r--src/shared/exit-status.h12
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);