Hello,
As discussed in https://github.com/systemd/systemd/issues/6690, there's a need
to add an option to the specific systemd services to be able to execute
arbitrary actions in the context of that particular service (think service
postgres initdb). Although, I do know that the current way to get this working
isn't too bad either, my making `foobar-action.service` like oneshot units to
do custom actions and split it into unit files, as these are the basic
constituent logic units that participate in the dependency graph. Though, there
are times when a service particularly needs many actions which may After
reflecting enough on the idea of units, I have something else to add. (I cannot
post to the mailing list because none of my email providers have a way to send
plain text mails, though this will be my last comment here, and probably the
closing one before this is taken to the mailing list for discussion).
THE CURRENT SITUATION:
systemctl mainly conforms to the LSB standard for service actions, and is not
supposed to support custom actions. Though, again, nothing stops it from
separating the standard service actions namespace from the generic actions
namespace.
The way systemd sets up dependency graphs, they're mainly done as dependencies
between units, participating in a boot transaction graph. Thus, adding custom
actions would mean there should be a way to depend on these custom defined
additions, which really does not fit into the working unit model which is a
really superior way of handling things. The boot is divided into these logical
units. The better way to do this is to have a foobar-action.service to the
desired action as a oneshot, but there still is a way to create these custom
actions as something that have dependencies in the unit itself as I showed
earlier, which aptly fits the use case where the action is too weak to lie in a
separate unit (again, very specific to the requirement). This model is not
perfect and I'll be happy to receive feedback on the ML. I'm also aware that
this will a lot of changes if we are to add them in the units, as there would
be change in the parsing engine, and the transaction and dependency graph
generator. After reflecting enough, it is also possible that the [Action] may
not quite fit the requirements of the custom action, for example, if it depends
on external units (which would lie outside of the dependency scope of the
block), in which case, a separate unit makes more sense.
As an immediate measure, you can use separate units to do your
graceful-restarts and logrotate and maybe add them as dependencies if required,
or configure your controlling client (or write a small script) to call these
units on the desired action, which is very neat tbh.
The current proposal needs some more polishing and *time*need to rely on a
certain action already strongly typed in the service like ExecStart= or
ExecStop= (or there Pre and Post) or ExecReload, or even before the stop+start
logic of restart (in simple words). Here, I am putting up some ideas I had
about the basic prototype of something that fits this particular need in
services.
WHAT I HAVE IN MIND:
Something along the lines of systemctl action=logrotate foobar.service
(actually, the action could lie after the service name so the bash/zsh
completion script could parse the unit and provide suggestions), and something
like Name= and then Exec=.... (and maybe still have the ExecPre=... and
ExecPost=... options for the Exec= action) in the service files, with these
custom commands in their own context block, like [Action] to be able to depend
on the generic ExecStart=, ExecStop=, ExecReload= commands, because then the
reopening of log files can be subjected with a restart or reload or w/e. (When
forming dependencies with a certain action, that action itself can have a
parameter action to call the custom command.) The order of execution will be
defined by the Before= or After= dependency of the command on the generic
action.
Example for doing a job:
[Unit]
...
[Service]
...
ExecStart=...
ExecStop=...
ExecReload=...
...
[Action]
Name=logrotate
# queue it before ExecStartPre or ExecStartPost, or After, as required.
Before=ExecStart
# Pre post for the Exec= directive
ExecPre=...
Exec=...
ExecPost=..
and then,
systemctl action=logrotate foobar.service
or
systemctl start action=logrotate foobar.service # would mean the same thing
Support could also be added to queue them as dependencies when being invoked
from the command line when a dependency isn't specified in the unit or cannot
be.
systemctl restart before-action=logrotate foobar.service
or
systemctl restart after-action=logrotate foobar.service
This though does have some use cases, there are times when the custom action
doesn't have to be queued before a generic action, and therefore it could be
something like this
[Unit]
...
[Service]
...
[Action]
Name=jobfoo
Exec=...
...
and then,
systemctl action=jobfoo foobar.service
We have the Exec= directive free, and it would make total sense to put it in a
ambiguous block and be used as required for blocks defining custom actions.
The Exec= thing being synchronous or asynchronous can be handled by the
command/script/binary being invoked.
As everyone must have noticed, this is something more complex to fit into the
current Unit specification scheme, but it is possible to fit in quite well, and
would really make the simple .ini model of the service files to be more
powerful. The proposal probably is not a very suitable scheme of integrating
custom commands into the unit, and may have a lot of deficiencies, suggestions
welcome. This really needs to be thought out well and be consistent with the
current unit file specification.
Also, right, the user should really not be able to redefine what restart (i.e.
start + stop) does, the behavior is correct.
All in all, custom commands do have a very strong use case, but they mustn't
lie in the generic namespace, instead be invoked with a parameter to an
argument instead. The issue can still be solved by making separate units for
custom actions, but, adding support to define custom service actions will
really be a plus and will be clean. Again, as proposed earlier, you could
divide the naming namespaces into two sections, the generic namespace and unit
specific namespace (which can be invoked with something like action). Although
trivial, there could be a file to define custom global actions that can be used
in all unit files created by the admin.
The idea really needs more refinement, polishing, and lots of time to make it
into systemd and be usable, but I was just hoping if there was any interest in
such a scheme for custom actions. I'd be happy to provide and receive more
feedback and discussion on this.
Regards,
Introoter
<introo...@protonmail.com>
----------------------------------------------------------------------------------------------------------
_______________________________________________
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/systemd-devel