mirror of
https://github.com/systemd/systemd.git
synced 2024-11-23 18:23:32 +08:00
service: allow services of Type=oneshot that specify no ExecStart= commands
This is useful for services that simply want to run something on shutdown, but not at bootup. They should only set ExecStop= but leave ExecStart= unset.
This commit is contained in:
parent
1954ea346d
commit
96fb8242cc
@ -139,9 +139,10 @@
|
||||
|
||||
<para>If set to
|
||||
<option>simple</option> (the default
|
||||
value if neither
|
||||
if neither
|
||||
<varname>Type=</varname> nor
|
||||
<varname>BusName=</varname> are
|
||||
<varname>BusName=</varname>, but
|
||||
<varname>ExecStart=</varname> are
|
||||
specified), it is expected that the
|
||||
process configured with
|
||||
<varname>ExecStart=</varname> is the
|
||||
@ -177,13 +178,17 @@
|
||||
exits.</para>
|
||||
|
||||
<para>Behavior of
|
||||
<option>oneshot</option> is similar
|
||||
to <option>simple</option>; however,
|
||||
it is expected that the process has to
|
||||
<option>oneshot</option> is similar to
|
||||
<option>simple</option>; however, it
|
||||
is expected that the process has to
|
||||
exit before systemd starts follow-up
|
||||
units. <varname>RemainAfterExit=</varname>
|
||||
is particularly useful for this type
|
||||
of service.</para>
|
||||
of service. This is the implied
|
||||
default if neither
|
||||
<varname>Type=</varname> or
|
||||
<varname>ExecStart=</varname> are
|
||||
specified.</para>
|
||||
|
||||
<para>Behavior of
|
||||
<option>dbus</option> is similar to
|
||||
@ -313,22 +318,27 @@
|
||||
|
||||
<para>When <varname>Type</varname> is
|
||||
not <option>oneshot</option>, only one
|
||||
command may be given. When
|
||||
command may and must be given. When
|
||||
<varname>Type=oneshot</varname> is
|
||||
used, more than one command may be
|
||||
specified. Multiple command lines may
|
||||
be concatenated in a single directive
|
||||
by separating them with semicolons
|
||||
(these semicolons must be passed as
|
||||
separate words). Alternatively, this
|
||||
directive may be specified more than
|
||||
once with the same effect.
|
||||
Lone semicolons may be escaped as
|
||||
used, none or more than one command
|
||||
may be specified. Multiple command
|
||||
lines may be concatenated in a single
|
||||
directive by separating them with
|
||||
semicolons (these semicolons must be
|
||||
passed as separate
|
||||
words). Alternatively, this directive
|
||||
may be specified more than once with
|
||||
the same effect. Lone semicolons may
|
||||
be escaped as
|
||||
<literal>\;</literal>. If the empty
|
||||
string is assigned to this option, the
|
||||
list of commands to start is reset,
|
||||
prior assignments of this option will
|
||||
have no effect.</para>
|
||||
have no effect. If no
|
||||
<varname>ExecStart=</varname> is
|
||||
specified, then the service must have
|
||||
<varname>RemainAfterExit=yes</varname>
|
||||
set.</para>
|
||||
|
||||
<para>Each command line is split on
|
||||
whitespace, with the first item being
|
||||
|
@ -313,14 +313,23 @@ static int service_verify(Service *s) {
|
||||
if (UNIT(s)->load_state != UNIT_LOADED)
|
||||
return 0;
|
||||
|
||||
if (!s->exec_command[SERVICE_EXEC_START]) {
|
||||
log_error_unit(UNIT(s)->id, "%s lacks ExecStart setting. Refusing.", UNIT(s)->id);
|
||||
if (!s->exec_command[SERVICE_EXEC_START] && !s->exec_command[SERVICE_EXEC_STOP]) {
|
||||
log_error_unit(UNIT(s)->id, "%s lacks both ExecStart= and ExecStop= setting. Refusing.", UNIT(s)->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (s->type != SERVICE_ONESHOT &&
|
||||
s->exec_command[SERVICE_EXEC_START]->command_next) {
|
||||
log_error_unit(UNIT(s)->id, "%s has more than one ExecStart setting, which is only allowed for Type=oneshot services. Refusing.", UNIT(s)->id);
|
||||
if (s->type != SERVICE_ONESHOT && !s->exec_command[SERVICE_EXEC_START]) {
|
||||
log_error_unit(UNIT(s)->id, "%s has no ExecStart= setting, which is only allowed for Type=oneshot services. Refusing.", UNIT(s)->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!s->remain_after_exit && !s->exec_command[SERVICE_EXEC_START]) {
|
||||
log_error_unit(UNIT(s)->id, "%s has no ExecStart= setting, which is only allowed for RemainAfterExit=yes services. Refusing.", UNIT(s)->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (s->type != SERVICE_ONESHOT && s->exec_command[SERVICE_EXEC_START]->command_next) {
|
||||
log_error_unit(UNIT(s)->id, "%s has more than one ExecStart= setting, which is only allowed for Type=oneshot services. Refusing.", UNIT(s)->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -410,8 +419,15 @@ static int service_load(Unit *u) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (s->type == _SERVICE_TYPE_INVALID)
|
||||
s->type = s->bus_name ? SERVICE_DBUS : SERVICE_SIMPLE;
|
||||
if (s->type == _SERVICE_TYPE_INVALID) {
|
||||
/* Figure out a type automatically */
|
||||
if (s->bus_name)
|
||||
s->type = SERVICE_DBUS;
|
||||
else if (s->exec_command[SERVICE_EXEC_START])
|
||||
s->type = SERVICE_SIMPLE;
|
||||
else
|
||||
s->type = SERVICE_ONESHOT;
|
||||
}
|
||||
|
||||
/* Oneshot services have disabled start timeout by default */
|
||||
if (s->type == SERVICE_ONESHOT && !s->start_timeout_defined)
|
||||
@ -1309,9 +1325,6 @@ static void service_enter_start(Service *s) {
|
||||
|
||||
assert(s);
|
||||
|
||||
assert(s->exec_command[SERVICE_EXEC_START]);
|
||||
assert(!s->exec_command[SERVICE_EXEC_START]->command_next || s->type == SERVICE_ONESHOT);
|
||||
|
||||
service_unwatch_control_pid(s);
|
||||
service_unwatch_main_pid(s);
|
||||
|
||||
@ -1332,6 +1345,12 @@ static void service_enter_start(Service *s) {
|
||||
c = s->main_command = s->exec_command[SERVICE_EXEC_START];
|
||||
}
|
||||
|
||||
if (!c) {
|
||||
assert(s->type == SERVICE_ONESHOT);
|
||||
service_enter_start_post(s);
|
||||
return;
|
||||
}
|
||||
|
||||
r = service_spawn(s,
|
||||
c,
|
||||
IN_SET(s->type, SERVICE_FORKING, SERVICE_DBUS, SERVICE_NOTIFY, SERVICE_ONESHOT) ? s->timeout_start_usec : 0,
|
||||
|
Loading…
Reference in New Issue
Block a user