service/systemctl: don't consider LSB exit codes 5 and 6 as failure, and decode exit codes in systemctl
This commit is contained in:
parent
8a2b3c097b
commit
d06dacd002
|
@ -299,6 +299,7 @@ libsystemd_core_la_SOURCES = \
|
||||||
src/path.c \
|
src/path.c \
|
||||||
src/load-dropin.c \
|
src/load-dropin.c \
|
||||||
src/execute.c \
|
src/execute.c \
|
||||||
|
src/exit-status.c \
|
||||||
src/dbus.c \
|
src/dbus.c \
|
||||||
src/dbus-manager.c \
|
src/dbus-manager.c \
|
||||||
src/dbus-unit.c \
|
src/dbus-unit.c \
|
||||||
|
@ -604,7 +605,8 @@ systemctl_SOURCES = \
|
||||||
src/path-lookup.c \
|
src/path-lookup.c \
|
||||||
src/sd-daemon.c \
|
src/sd-daemon.c \
|
||||||
src/cgroup-show.c \
|
src/cgroup-show.c \
|
||||||
src/cgroup-util.c
|
src/cgroup-util.c \
|
||||||
|
src/exit-status.c
|
||||||
|
|
||||||
systemctl_CFLAGS = \
|
systemctl_CFLAGS = \
|
||||||
$(AM_CFLAGS) \
|
$(AM_CFLAGS) \
|
||||||
|
|
6
fixme
6
fixme
|
@ -58,11 +58,7 @@
|
||||||
|
|
||||||
* if a service fails too often, make the service enter maintenance mode, and the socket, too.
|
* if a service fails too often, make the service enter maintenance mode, and the socket, too.
|
||||||
|
|
||||||
* exit code 5, 6 von sysv diensten ignorieren
|
* systemctl: warning wenn [Install] leer ist bei enable
|
||||||
|
|
||||||
* decode exit codes in systemctl status
|
|
||||||
|
|
||||||
* systemctl: ln -s output muss abschaltbar sein, und warning wenn [Install] leer ist.
|
|
||||||
|
|
||||||
* bash completion a la gdbus
|
* bash completion a la gdbus
|
||||||
|
|
||||||
|
|
112
src/execute.c
112
src/execute.c
|
@ -51,6 +51,7 @@
|
||||||
#include "cgroup.h"
|
#include "cgroup.h"
|
||||||
#include "namespace.h"
|
#include "namespace.h"
|
||||||
#include "tcpwrap.h"
|
#include "tcpwrap.h"
|
||||||
|
#include "exit-status.h"
|
||||||
|
|
||||||
/* This assumes there is a 'tty' group */
|
/* This assumes there is a 'tty' group */
|
||||||
#define TTY_MODE 0620
|
#define TTY_MODE 0620
|
||||||
|
@ -1757,117 +1758,6 @@ int exec_command_set(ExecCommand *c, const char *path, ...) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* exit_status_to_string(ExitStatus status) {
|
|
||||||
|
|
||||||
/* We cast to int here, so that -Wenum doesn't complain that
|
|
||||||
* EXIT_SUCCESS/EXIT_FAILURE aren't in the enum */
|
|
||||||
|
|
||||||
switch ((int) status) {
|
|
||||||
|
|
||||||
case EXIT_SUCCESS:
|
|
||||||
return "SUCCESS";
|
|
||||||
|
|
||||||
case EXIT_FAILURE:
|
|
||||||
return "FAILURE";
|
|
||||||
|
|
||||||
case EXIT_INVALIDARGUMENT:
|
|
||||||
return "INVALIDARGUMENT";
|
|
||||||
|
|
||||||
case EXIT_NOTIMPLEMENTED:
|
|
||||||
return "NOTIMPLEMENTED";
|
|
||||||
|
|
||||||
case EXIT_NOPERMISSION:
|
|
||||||
return "NOPERMISSION";
|
|
||||||
|
|
||||||
case EXIT_NOTINSTALLED:
|
|
||||||
return "NOTINSSTALLED";
|
|
||||||
|
|
||||||
case EXIT_NOTCONFIGURED:
|
|
||||||
return "NOTCONFIGURED";
|
|
||||||
|
|
||||||
case EXIT_NOTRUNNING:
|
|
||||||
return "NOTRUNNING";
|
|
||||||
|
|
||||||
case EXIT_CHDIR:
|
|
||||||
return "CHDIR";
|
|
||||||
|
|
||||||
case EXIT_NICE:
|
|
||||||
return "NICE";
|
|
||||||
|
|
||||||
case EXIT_FDS:
|
|
||||||
return "FDS";
|
|
||||||
|
|
||||||
case EXIT_EXEC:
|
|
||||||
return "EXEC";
|
|
||||||
|
|
||||||
case EXIT_MEMORY:
|
|
||||||
return "MEMORY";
|
|
||||||
|
|
||||||
case EXIT_LIMITS:
|
|
||||||
return "LIMITS";
|
|
||||||
|
|
||||||
case EXIT_OOM_ADJUST:
|
|
||||||
return "OOM_ADJUST";
|
|
||||||
|
|
||||||
case EXIT_SIGNAL_MASK:
|
|
||||||
return "SIGNAL_MASK";
|
|
||||||
|
|
||||||
case EXIT_STDIN:
|
|
||||||
return "STDIN";
|
|
||||||
|
|
||||||
case EXIT_STDOUT:
|
|
||||||
return "STDOUT";
|
|
||||||
|
|
||||||
case EXIT_CHROOT:
|
|
||||||
return "CHROOT";
|
|
||||||
|
|
||||||
case EXIT_IOPRIO:
|
|
||||||
return "IOPRIO";
|
|
||||||
|
|
||||||
case EXIT_TIMERSLACK:
|
|
||||||
return "TIMERSLACK";
|
|
||||||
|
|
||||||
case EXIT_SECUREBITS:
|
|
||||||
return "SECUREBITS";
|
|
||||||
|
|
||||||
case EXIT_SETSCHEDULER:
|
|
||||||
return "SETSCHEDULER";
|
|
||||||
|
|
||||||
case EXIT_CPUAFFINITY:
|
|
||||||
return "CPUAFFINITY";
|
|
||||||
|
|
||||||
case EXIT_GROUP:
|
|
||||||
return "GROUP";
|
|
||||||
|
|
||||||
case EXIT_USER:
|
|
||||||
return "USER";
|
|
||||||
|
|
||||||
case EXIT_CAPABILITIES:
|
|
||||||
return "CAPABILITIES";
|
|
||||||
|
|
||||||
case EXIT_CGROUP:
|
|
||||||
return "CGROUP";
|
|
||||||
|
|
||||||
case EXIT_SETSID:
|
|
||||||
return "SETSID";
|
|
||||||
|
|
||||||
case EXIT_CONFIRM:
|
|
||||||
return "CONFIRM";
|
|
||||||
|
|
||||||
case EXIT_STDERR:
|
|
||||||
return "STDERR";
|
|
||||||
|
|
||||||
case EXIT_TCPWRAP:
|
|
||||||
return "TCPWRAP";
|
|
||||||
|
|
||||||
case EXIT_PAM:
|
|
||||||
return "PAM";
|
|
||||||
|
|
||||||
default:
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char* const exec_input_table[_EXEC_INPUT_MAX] = {
|
static const char* const exec_input_table[_EXEC_INPUT_MAX] = {
|
||||||
[EXEC_INPUT_NULL] = "null",
|
[EXEC_INPUT_NULL] = "null",
|
||||||
[EXEC_INPUT_TTY] = "tty",
|
[EXEC_INPUT_TTY] = "tty",
|
||||||
|
|
|
@ -160,50 +160,6 @@ struct ExecContext {
|
||||||
bool timer_slack_nsec_set:1;
|
bool timer_slack_nsec_set:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum ExitStatus {
|
|
||||||
/* EXIT_SUCCESS defined by libc */
|
|
||||||
/* EXIT_FAILURE defined by libc */
|
|
||||||
EXIT_INVALIDARGUMENT = 2,
|
|
||||||
EXIT_NOTIMPLEMENTED = 3,
|
|
||||||
EXIT_NOPERMISSION = 4,
|
|
||||||
EXIT_NOTINSTALLED = 5,
|
|
||||||
EXIT_NOTCONFIGURED = 6,
|
|
||||||
EXIT_NOTRUNNING = 7,
|
|
||||||
|
|
||||||
/* The LSB suggests that error codes >= 200 are "reserved". We
|
|
||||||
* use them here under the assumption that they hence are
|
|
||||||
* unused by init scripts.
|
|
||||||
*
|
|
||||||
* http://refspecs.freestandards.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html */
|
|
||||||
|
|
||||||
EXIT_CHDIR = 200,
|
|
||||||
EXIT_NICE,
|
|
||||||
EXIT_FDS,
|
|
||||||
EXIT_EXEC,
|
|
||||||
EXIT_MEMORY,
|
|
||||||
EXIT_LIMITS,
|
|
||||||
EXIT_OOM_ADJUST,
|
|
||||||
EXIT_SIGNAL_MASK,
|
|
||||||
EXIT_STDIN,
|
|
||||||
EXIT_STDOUT,
|
|
||||||
EXIT_CHROOT, /* 210 */
|
|
||||||
EXIT_IOPRIO,
|
|
||||||
EXIT_TIMERSLACK,
|
|
||||||
EXIT_SECUREBITS,
|
|
||||||
EXIT_SETSCHEDULER,
|
|
||||||
EXIT_CPUAFFINITY,
|
|
||||||
EXIT_GROUP,
|
|
||||||
EXIT_USER,
|
|
||||||
EXIT_CAPABILITIES,
|
|
||||||
EXIT_CGROUP,
|
|
||||||
EXIT_SETSID, /* 220 */
|
|
||||||
EXIT_CONFIRM,
|
|
||||||
EXIT_STDERR,
|
|
||||||
EXIT_TCPWRAP,
|
|
||||||
EXIT_PAM
|
|
||||||
|
|
||||||
} ExitStatus;
|
|
||||||
|
|
||||||
int exec_spawn(ExecCommand *command,
|
int exec_spawn(ExecCommand *command,
|
||||||
char **argv,
|
char **argv,
|
||||||
const ExecContext *context,
|
const ExecContext *context,
|
||||||
|
@ -243,6 +199,4 @@ int exec_output_from_string(const char *s);
|
||||||
const char* exec_input_to_string(ExecInput i);
|
const char* exec_input_to_string(ExecInput i);
|
||||||
int exec_input_from_string(const char *s);
|
int exec_input_from_string(const char *s);
|
||||||
|
|
||||||
const char* exit_status_to_string(ExitStatus status);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
#include "path-lookup.h"
|
#include "path-lookup.h"
|
||||||
#include "special.h"
|
#include "special.h"
|
||||||
#include "bus-errors.h"
|
#include "bus-errors.h"
|
||||||
|
#include "exit-status.h"
|
||||||
|
|
||||||
/* As soon as 16 units are in our GC queue, make sure to run a gc sweep */
|
/* As soon as 16 units are in our GC queue, make sure to run a gc sweep */
|
||||||
#define GC_QUEUE_ENTRIES_MAX 16
|
#define GC_QUEUE_ENTRIES_MAX 16
|
||||||
|
@ -1885,7 +1886,9 @@ static int manager_dispatch_sigchld(Manager *m) {
|
||||||
(long unsigned) si.si_pid,
|
(long unsigned) si.si_pid,
|
||||||
sigchld_code_to_string(si.si_code),
|
sigchld_code_to_string(si.si_code),
|
||||||
si.si_status,
|
si.si_status,
|
||||||
strna(si.si_code == CLD_EXITED ? exit_status_to_string(si.si_status) : signal_to_string(si.si_status)));
|
strna(si.si_code == CLD_EXITED
|
||||||
|
? exit_status_to_string(si.si_status, EXIT_STATUS_FULL)
|
||||||
|
: signal_to_string(si.si_status)));
|
||||||
|
|
||||||
if (!u)
|
if (!u)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -2263,7 +2263,10 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||||
assert(s);
|
assert(s);
|
||||||
assert(pid >= 0);
|
assert(pid >= 0);
|
||||||
|
|
||||||
success = is_clean_exit(code, status);
|
if (s->sysv_path)
|
||||||
|
success = is_clean_exit_lsb(code, status);
|
||||||
|
else
|
||||||
|
success = is_clean_exit(code, status);
|
||||||
|
|
||||||
if (s->main_pid == pid) {
|
if (s->main_pid == pid) {
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
#include "conf-parser.h"
|
#include "conf-parser.h"
|
||||||
#include "sd-daemon.h"
|
#include "sd-daemon.h"
|
||||||
#include "shutdownd.h"
|
#include "shutdownd.h"
|
||||||
|
#include "exit-status.h"
|
||||||
|
|
||||||
static const char *arg_type = NULL;
|
static const char *arg_type = NULL;
|
||||||
static char **arg_property = NULL;
|
static char **arg_property = NULL;
|
||||||
|
@ -1489,7 +1490,8 @@ typedef struct UnitStatusInfo {
|
||||||
pid_t main_pid;
|
pid_t main_pid;
|
||||||
pid_t control_pid;
|
pid_t control_pid;
|
||||||
const char *status_text;
|
const char *status_text;
|
||||||
bool running;
|
bool running:1;
|
||||||
|
bool is_sysv:1;
|
||||||
|
|
||||||
usec_t start_timestamp;
|
usec_t start_timestamp;
|
||||||
usec_t exit_timestamp;
|
usec_t exit_timestamp;
|
||||||
|
@ -1584,9 +1586,15 @@ static void print_status_info(UnitStatusInfo *i) {
|
||||||
printf("\t Exited: %u (%s, code=%s, ", p->pid, strna(t), sigchld_code_to_string(p->code));
|
printf("\t Exited: %u (%s, code=%s, ", p->pid, strna(t), sigchld_code_to_string(p->code));
|
||||||
free(t);
|
free(t);
|
||||||
|
|
||||||
if (p->code == CLD_EXITED)
|
if (p->code == CLD_EXITED) {
|
||||||
|
const char *c;
|
||||||
|
|
||||||
printf("status=%i", p->status);
|
printf("status=%i", p->status);
|
||||||
else
|
|
||||||
|
if ((c = exit_status_to_string(p->status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
|
||||||
|
printf("/%s", c);
|
||||||
|
|
||||||
|
} else
|
||||||
printf("signal=%s", signal_to_string(p->status));
|
printf("signal=%s", signal_to_string(p->status));
|
||||||
printf(")\n");
|
printf(")\n");
|
||||||
|
|
||||||
|
@ -1616,9 +1624,15 @@ static void print_status_info(UnitStatusInfo *i) {
|
||||||
} else if (i->exit_code > 0) {
|
} else if (i->exit_code > 0) {
|
||||||
printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
|
printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
|
||||||
|
|
||||||
if (i->exit_code == CLD_EXITED)
|
if (i->exit_code == CLD_EXITED) {
|
||||||
|
const char *c;
|
||||||
|
|
||||||
printf("status=%i", i->exit_status);
|
printf("status=%i", i->exit_status);
|
||||||
else
|
|
||||||
|
if ((c = exit_status_to_string(i->exit_status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
|
||||||
|
printf("/%s", c);
|
||||||
|
|
||||||
|
} else
|
||||||
printf("signal=%s", signal_to_string(i->exit_status));
|
printf("signal=%s", signal_to_string(i->exit_status));
|
||||||
printf(")");
|
printf(")");
|
||||||
}
|
}
|
||||||
|
@ -1687,9 +1701,10 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
|
||||||
i->description = s;
|
i->description = s;
|
||||||
else if (streq(name, "FragmentPath"))
|
else if (streq(name, "FragmentPath"))
|
||||||
i->path = s;
|
i->path = s;
|
||||||
else if (streq(name, "SysVPath"))
|
else if (streq(name, "SysVPath")) {
|
||||||
|
i->is_sysv = true;
|
||||||
i->path = s;
|
i->path = s;
|
||||||
else if (streq(name, "DefaultControlGroup"))
|
} else if (streq(name, "DefaultControlGroup"))
|
||||||
i->default_control_group = s;
|
i->default_control_group = s;
|
||||||
else if (streq(name, "StatusText"))
|
else if (streq(name, "StatusText"))
|
||||||
i->status_text = s;
|
i->status_text = s;
|
||||||
|
|
11
src/util.c
11
src/util.c
|
@ -57,6 +57,7 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "label.h"
|
#include "label.h"
|
||||||
|
#include "exit-status.h"
|
||||||
|
|
||||||
bool streq_ptr(const char *a, const char *b) {
|
bool streq_ptr(const char *a, const char *b) {
|
||||||
|
|
||||||
|
@ -2398,6 +2399,16 @@ bool is_clean_exit(int code, int status) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_clean_exit_lsb(int code, int status) {
|
||||||
|
|
||||||
|
if (is_clean_exit(code, status))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return
|
||||||
|
code == CLD_EXITED &&
|
||||||
|
(status == EXIT_NOTINSTALLED || status == EXIT_NOTCONFIGURED);
|
||||||
|
}
|
||||||
|
|
||||||
bool is_device_path(const char *path) {
|
bool is_device_path(const char *path) {
|
||||||
|
|
||||||
/* Returns true on paths that refer to a device, either in
|
/* Returns true on paths that refer to a device, either in
|
||||||
|
|
|
@ -253,6 +253,7 @@ char *format_timespan(char *buf, size_t l, usec_t t);
|
||||||
int make_stdio(int fd);
|
int make_stdio(int fd);
|
||||||
|
|
||||||
bool is_clean_exit(int code, int status);
|
bool is_clean_exit(int code, int status);
|
||||||
|
bool is_clean_exit_lsb(int code, int status);
|
||||||
|
|
||||||
unsigned long long random_ull(void);
|
unsigned long long random_ull(void);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue