0

I want a bash script to complete its work (not just start) before a certain systemd service, the solution to which AFAIK involves finishing before its own service has finished.

Web search finds questions about how to start. As I understand Before= option is to wait until unit had been started. Therefore reading man systemd.service I see only one option: Type=forking:

the service manager will consider the unit started when the parent process exits.

even as I do not fork any processes in a script. Am I correct here? Will that guarantee (apart from bugs, etc.) that my script will complete before service in Before= is started?

E.g. other type: Type=exec:

"while exec will not proceed before both fork() and execve() in the service process succeeded."

Unclear to me what proceed here means, also reading man execve I do not understand how systemd will know if execve succeed as:

execve() does not return on success, and the text, initialized data, uninitialized data (bss), and stack of the calling process are overwritten according to the contents of the newly loaded program.

Other types (notify, dbus) as I see from man need special capabilities from the process started.

2
  • Does this answer your question? How can I get a systemd service to finish before running a new service?
    – FelixJN
    Oct 10, 2023 at 11:43
  • @FelixJN, no. Completing a unit does not mean completing a process in ExecStart= per se (and for Type=simple it is expressely stated in man page as I see it ("simple services will report success even if the service's binary cannot be invoked successfully"). Hence I noted only for "forking" something close to what I need is stated explicitly, but would like a confirmation. Oct 10, 2023 at 12:06

1 Answer 1

2

I think you are fine using type=oneshot with RemainAfterExit=true; from the documentation

Behavior of oneshot is similar to simple; however, the service manager will consider the unit up after the main process exits. It will then start follow-up units. RemainAfterExit= is particularly useful for this type of service. Type=oneshot is the implied default if neither Type= nor ExecStart= are specified. Note that if this option is used without RemainAfterExit= the service will never enter "active" unit state, but directly transition from "activating" to "deactivating" or "dead" since no process is configured that shall run continuously. In particular this means that after a service of this type ran (and which has RemainAfterExit= not set) it will not show up as started afterwards, but as dead.

It may not be fully clear, what the main process is, but looking at the explanation for ExecStart= one finds:

Unless Type=forking is set, the process started via this command line will be considered the main process of the daemon.


EDIT

Note that Type=oneshot is the only kind that allows for multiple ExecStart= options. They are executed in one after the other in the order they appear, and each of them is the respective main process while it runs.

See the manuals again:

ExecStart=

Commands that are executed when this service is started. The value is split into zero or more command lines according to the rules described in the section "Command Lines" below.

Unless Type= is oneshot, exactly one command must be given. When Type=oneshot is used, zero or more commands may be specified. Commands may be specified by providing multiple command lines in the same directive, or alternatively, this directive may be specified more than once with the same effect. 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. If no ExecStart= is specified, then the service must have RemainAfterExit=yes and at least one ExecStop= line set. (Services lacking both ExecStart= and ExecStop= are not valid.)

If more than one command is specified, the commands are invoked sequentially in the order they appear in the unit file. If one of the commands fails (and is not prefixed with "-"), other lines are not executed, and the unit is considered failed.

3
  • Seems corrent, though for Oneshot there could be several main processes that way, so does " the unit up after the main process exits" mean 1st of main processes or alfter all of them? I actually initially understood that part (though I suspect I'm wrong as word "unit" is used) as next ExecStart is started after previous exits. Oct 11, 2023 at 9:35
  • 1
    @AlexMartian see updates in answer. This case is described very well. Each command is executed one after the other, the unit only consiedered active/up if all commands succeed, and the command series is aborted in case any command fails.
    – FelixJN
    Oct 11, 2023 at 11:18
  • Thank you. I'm starting to see it is likely Ok given all the context of what unit, success, process etc. are. I need some time to ponder on that a bit. Oct 11, 2023 at 11:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .