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

Reply via email to