execute: optionally ignore return status of invoked commands
This commit is contained in:
parent
f1dfb62962
commit
b708e7cea9
8
fixme
8
fixme
|
@ -35,12 +35,12 @@
|
||||||
|
|
||||||
* selinux
|
* selinux
|
||||||
|
|
||||||
* Show exit status auf auxiliary programs in systemctl status
|
|
||||||
|
|
||||||
* rtkit status
|
|
||||||
|
|
||||||
* systemctl status $PID, systemctl stop $PID!
|
* systemctl status $PID, systemctl stop $PID!
|
||||||
|
|
||||||
|
* make shutdown go on even if conflicting units fail to shut down.
|
||||||
|
|
||||||
|
* sulogin in den single user mode, mit plymouth --hide davor
|
||||||
|
|
||||||
External:
|
External:
|
||||||
|
|
||||||
* patch /etc/init.d/functions with:
|
* patch /etc/init.d/functions with:
|
||||||
|
|
|
@ -256,7 +256,15 @@
|
||||||
token will be passed as
|
token will be passed as
|
||||||
<literal>argv[0]</literal> to the
|
<literal>argv[0]</literal> to the
|
||||||
executed process, followed by the
|
executed process, followed by the
|
||||||
further arguments specified. Unless
|
further arguments specified. If the
|
||||||
|
first token is prefixed with
|
||||||
|
<literal>-</literal> an error code of
|
||||||
|
the command normally considered a
|
||||||
|
failure is ignored and considered
|
||||||
|
success. If both <literal>-</literal>
|
||||||
|
and <literal>@</literal> are used for
|
||||||
|
the same command the latter must
|
||||||
|
preceed the latter. Unless
|
||||||
<varname>Type=forking</varname> is
|
<varname>Type=forking</varname> is
|
||||||
set, the process started via this
|
set, the process started via this
|
||||||
command line will be considered the
|
command line will be considered the
|
||||||
|
|
|
@ -258,7 +258,7 @@ int bus_execute_append_command(Manager *m, DBusMessageIter *i, const char *prope
|
||||||
assert(i);
|
assert(i);
|
||||||
assert(property);
|
assert(property);
|
||||||
|
|
||||||
if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sasttuii)", &sub))
|
if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sasbttuii)", &sub))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
LIST_FOREACH(command, c, c) {
|
LIST_FOREACH(command, c, c) {
|
||||||
|
@ -283,6 +283,7 @@ int bus_execute_append_command(Manager *m, DBusMessageIter *i, const char *prope
|
||||||
status = (int32_t) c->exec_status.status;
|
status = (int32_t) c->exec_status.status;
|
||||||
|
|
||||||
if (!dbus_message_iter_close_container(&sub2, &sub3) ||
|
if (!dbus_message_iter_close_container(&sub2, &sub3) ||
|
||||||
|
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &c->ignore) ||
|
||||||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.realtime) ||
|
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.realtime) ||
|
||||||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.realtime) ||
|
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.realtime) ||
|
||||||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &c->exec_status.pid) ||
|
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &c->exec_status.pid) ||
|
||||||
|
|
|
@ -88,7 +88,7 @@
|
||||||
" <property name=\"KillSignal\" type=\"i\" access=\"read\"/>\n"
|
" <property name=\"KillSignal\" type=\"i\" access=\"read\"/>\n"
|
||||||
|
|
||||||
#define BUS_EXEC_COMMAND_INTERFACE(name) \
|
#define BUS_EXEC_COMMAND_INTERFACE(name) \
|
||||||
" <property name=\"" name "\" type=\"a(sasttuii)\" access=\"read\"/>\n"
|
" <property name=\"" name "\" type=\"a(sasbttuii)\" access=\"read\"/>\n"
|
||||||
|
|
||||||
#define BUS_EXEC_CONTEXT_PROPERTIES(interface, context) \
|
#define BUS_EXEC_CONTEXT_PROPERTIES(interface, context) \
|
||||||
{ interface, "Environment", bus_property_append_strv, "as", (context).environment }, \
|
{ interface, "Environment", bus_property_append_strv, "as", (context).environment }, \
|
||||||
|
@ -152,7 +152,7 @@
|
||||||
{ interface, prefix "Status", bus_property_append_int, "i", &(estatus).status }
|
{ interface, prefix "Status", bus_property_append_int, "i", &(estatus).status }
|
||||||
|
|
||||||
#define BUS_EXEC_COMMAND_PROPERTY(interface, command, name) \
|
#define BUS_EXEC_COMMAND_PROPERTY(interface, command, name) \
|
||||||
{ interface, name, bus_execute_append_command, "a(sasttuii)", (command) }
|
{ interface, name, bus_execute_append_command, "a(sasbttuii)", (command) }
|
||||||
|
|
||||||
int bus_execute_append_output(Manager *m, DBusMessageIter *i, const char *property, void *data);
|
int bus_execute_append_output(Manager *m, DBusMessageIter *i, const char *property, void *data);
|
||||||
int bus_execute_append_input(Manager *m, DBusMessageIter *i, const char *property, void *data);
|
int bus_execute_append_input(Manager *m, DBusMessageIter *i, const char *property, void *data);
|
||||||
|
|
|
@ -87,6 +87,7 @@ struct ExecCommand {
|
||||||
char *path;
|
char *path;
|
||||||
char **argv;
|
char **argv;
|
||||||
ExecStatus exec_status;
|
ExecStatus exec_status;
|
||||||
|
bool ignore;
|
||||||
LIST_FIELDS(ExecCommand, command); /* useful for chaining commands */
|
LIST_FIELDS(ExecCommand, command); /* useful for chaining commands */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -382,7 +382,7 @@ static int config_parse_exec(
|
||||||
char *w;
|
char *w;
|
||||||
size_t l;
|
size_t l;
|
||||||
char *state;
|
char *state;
|
||||||
bool honour_argv0, write_to_path;
|
bool honour_argv0 = false, ignore = false;
|
||||||
|
|
||||||
path = NULL;
|
path = NULL;
|
||||||
nce = NULL;
|
nce = NULL;
|
||||||
|
@ -393,9 +393,17 @@ static int config_parse_exec(
|
||||||
if (rvalue[0] == 0)
|
if (rvalue[0] == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
honour_argv0 = rvalue[0] == '@';
|
if (rvalue[0] == '-') {
|
||||||
|
ignore = true;
|
||||||
|
rvalue ++;
|
||||||
|
}
|
||||||
|
|
||||||
if (rvalue[honour_argv0 ? 1 : 0] != '/') {
|
if (rvalue[0] == '@') {
|
||||||
|
honour_argv0 = true;
|
||||||
|
rvalue ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*rvalue != '/') {
|
||||||
log_error("[%s:%u] Invalid executable path in command line: %s", filename, line, rvalue);
|
log_error("[%s:%u] Invalid executable path in command line: %s", filename, line, rvalue);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -408,19 +416,18 @@ static int config_parse_exec(
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(n = new(char*, k + (honour_argv0 ? 0 : 1))))
|
if (!(n = new(char*, k + !honour_argv0)))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
k = 0;
|
k = 0;
|
||||||
write_to_path = honour_argv0;
|
|
||||||
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
|
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
|
||||||
if (strncmp(w, ";", l) == 0)
|
if (strncmp(w, ";", l) == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (write_to_path) {
|
if (honour_argv0 && w == rvalue) {
|
||||||
if (!(path = cunescape_length(w+1, l-1)))
|
assert(!path);
|
||||||
|
if (!(path = cunescape_length(w, l)))
|
||||||
goto fail;
|
goto fail;
|
||||||
write_to_path = false;
|
|
||||||
} else {
|
} else {
|
||||||
if (!(n[k++] = cunescape_length(w, l)))
|
if (!(n[k++] = cunescape_length(w, l)))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -446,6 +453,7 @@ static int config_parse_exec(
|
||||||
|
|
||||||
nce->argv = n;
|
nce->argv = n;
|
||||||
nce->path = path;
|
nce->path = path;
|
||||||
|
nce->ignore = ignore;
|
||||||
|
|
||||||
path_kill_slashes(nce->path);
|
path_kill_slashes(nce->path);
|
||||||
|
|
||||||
|
|
|
@ -2171,7 +2171,6 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||||
assert(pid >= 0);
|
assert(pid >= 0);
|
||||||
|
|
||||||
success = is_clean_exit(code, status);
|
success = is_clean_exit(code, status);
|
||||||
s->failure = s->failure || !success;
|
|
||||||
|
|
||||||
if (s->main_pid == pid) {
|
if (s->main_pid == pid) {
|
||||||
|
|
||||||
|
@ -2181,9 +2180,13 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||||
if (s->type != SERVICE_FORKING) {
|
if (s->type != SERVICE_FORKING) {
|
||||||
assert(s->exec_command[SERVICE_EXEC_START]);
|
assert(s->exec_command[SERVICE_EXEC_START]);
|
||||||
s->exec_command[SERVICE_EXEC_START]->exec_status = s->main_exec_status;
|
s->exec_command[SERVICE_EXEC_START]->exec_status = s->main_exec_status;
|
||||||
|
|
||||||
|
if (s->exec_command[SERVICE_EXEC_START]->ignore)
|
||||||
|
success = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_debug("%s: main process exited, code=%s, status=%i", u->meta.id, sigchld_code_to_string(code), status);
|
log_debug("%s: main process exited, code=%s, status=%i", u->meta.id, sigchld_code_to_string(code), status);
|
||||||
|
s->failure = s->failure || !success;
|
||||||
|
|
||||||
/* The service exited, so the service is officially
|
/* The service exited, so the service is officially
|
||||||
* gone. */
|
* gone. */
|
||||||
|
@ -2230,12 +2233,17 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||||
|
|
||||||
} else if (s->control_pid == pid) {
|
} else if (s->control_pid == pid) {
|
||||||
|
|
||||||
if (s->control_command)
|
if (s->control_command) {
|
||||||
exec_status_exit(&s->control_command->exec_status, pid, code, status);
|
exec_status_exit(&s->control_command->exec_status, pid, code, status);
|
||||||
|
|
||||||
|
if (s->control_command->ignore)
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
s->control_pid = 0;
|
s->control_pid = 0;
|
||||||
|
|
||||||
log_debug("%s: control process exited, code=%s status=%i", u->meta.id, sigchld_code_to_string(code), status);
|
log_debug("%s: control process exited, code=%s status=%i", u->meta.id, sigchld_code_to_string(code), status);
|
||||||
|
s->failure = s->failure || !success;
|
||||||
|
|
||||||
/* If we are shutting things down anyway we
|
/* If we are shutting things down anyway we
|
||||||
* don't care about failing commands. */
|
* don't care about failing commands. */
|
||||||
|
|
|
@ -1400,12 +1400,16 @@ static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||||
s->control_pid = 0;
|
s->control_pid = 0;
|
||||||
|
|
||||||
success = is_clean_exit(code, status);
|
success = is_clean_exit(code, status);
|
||||||
s->failure = s->failure || !success;
|
|
||||||
|
|
||||||
if (s->control_command)
|
if (s->control_command) {
|
||||||
exec_status_exit(&s->control_command->exec_status, pid, code, status);
|
exec_status_exit(&s->control_command->exec_status, pid, code, status);
|
||||||
|
|
||||||
|
if (s->control_command->ignore)
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
log_debug("%s control process exited, code=%s status=%i", u->meta.id, sigchld_code_to_string(code), status);
|
log_debug("%s control process exited, code=%s status=%i", u->meta.id, sigchld_code_to_string(code), status);
|
||||||
|
s->failure = s->failure || !success;
|
||||||
|
|
||||||
if (s->control_command && s->control_command->command_next && success) {
|
if (s->control_command && s->control_command->command_next && success) {
|
||||||
log_debug("%s running next command for state %s", u->meta.id, socket_state_to_string(s->state));
|
log_debug("%s running next command for state %s", u->meta.id, socket_state_to_string(s->state));
|
||||||
|
|
|
@ -933,6 +933,8 @@ typedef struct ExecStatusInfo {
|
||||||
char *path;
|
char *path;
|
||||||
char **argv;
|
char **argv;
|
||||||
|
|
||||||
|
bool ignore;
|
||||||
|
|
||||||
usec_t start_timestamp;
|
usec_t start_timestamp;
|
||||||
usec_t exit_timestamp;
|
usec_t exit_timestamp;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
@ -957,6 +959,7 @@ static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i)
|
||||||
unsigned n;
|
unsigned n;
|
||||||
uint32_t pid;
|
uint32_t pid;
|
||||||
int32_t code, status;
|
int32_t code, status;
|
||||||
|
dbus_bool_t ignore;
|
||||||
|
|
||||||
assert(i);
|
assert(i);
|
||||||
assert(i);
|
assert(i);
|
||||||
|
@ -1002,6 +1005,7 @@ static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dbus_message_iter_next(&sub2) ||
|
if (!dbus_message_iter_next(&sub2) ||
|
||||||
|
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
|
||||||
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
|
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
|
||||||
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
|
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
|
||||||
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
|
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
|
||||||
|
@ -1009,6 +1013,7 @@ static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i)
|
||||||
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
|
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
|
i->ignore = ignore;
|
||||||
i->start_timestamp = (usec_t) start_timestamp;
|
i->start_timestamp = (usec_t) start_timestamp;
|
||||||
i->exit_timestamp = (usec_t) exit_timestamp;
|
i->exit_timestamp = (usec_t) exit_timestamp;
|
||||||
i->pid = (pid_t) pid;
|
i->pid = (pid_t) pid;
|
||||||
|
@ -1535,10 +1540,11 @@ static int print_property(const char *name, DBusMessageIter *iter) {
|
||||||
|
|
||||||
t = strv_join(info.argv, " ");
|
t = strv_join(info.argv, " ");
|
||||||
|
|
||||||
printf("%s={ path=%s ; argv[]=%s; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
|
printf("%s={ path=%s ; argv[]=%s ; ignore=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
|
||||||
name,
|
name,
|
||||||
strna(info.path),
|
strna(info.path),
|
||||||
strna(t),
|
strna(t),
|
||||||
|
yes_no(info.ignore),
|
||||||
strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
|
strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
|
||||||
strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
|
strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
|
||||||
(unsigned) info. pid,
|
(unsigned) info. pid,
|
||||||
|
|
Loading…
Reference in a new issue