<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>
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;
} 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;
"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"
"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,
{ "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 },
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: {
}
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
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 */
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))
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)
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:
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);
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");
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
#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
bool taint_usr:1;
- bool show_status;
+ ShowStatus show_status;
bool confirm_spawn;
bool no_console_output;
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);
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,
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);
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;
+}
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);