5

I think I have a relatively good handle on the different Type of services which systemd can be configured for (e.g. simple, oneshot, etc).

The docs provide a pretty reasonable overview and description of the options. So often it's possible to "guess" the likely best option and do 'trial and error' to confirm. That is especially the case with applications that I'm quite familiar with.

However, I am concerned that there may be circumstance I'm not accounting for during my 'trial and error' testing (i.e. risk of edge case bugs). So I'm after suggestions on methods of testing/investigating an application to determine it's likely best Type.

FWIW, I'm thinking of some way of manually launching an application and tracing how it responds, whether it forks or not (multiple processes, etc). I feel like there must be some relatively easy way to do that (using standard commandline tools) that I'm missing.

I'm not sure if it's relevant, but Debian is my distro of choice.

6
  • 2
    Joke on systemd: if there were "some relatively easy way to do that (using standard commandline tools)" they would have either (a) already incorporated that, or (b) re-invented it.
    – muru
    Oct 3, 2019 at 5:37
  • @muru That is pretty funny! :D Oct 3, 2019 at 5:57
  • 2
  • 2
    Also consider that often the right answer is not really derive Type from a program's behavior (e.g. Type=forking) but instead to modify the program's behavior (to not daemonize) in order to use a more appropriate Type (such as Type=simple). Also more integration with systemd is usually pretty beneficial and often enables powerful features (such as socket activation), so the best answer is that it's up to the developers to provide systemd units together with their code, so they can take full benefit of full integration.
    – filbranden
    Oct 3, 2019 at 9:47
  • 1
    Good point @filbranden. Obviously that's not so easy when working with someone else's software, although with FLOSS, improvements could always be contributed back. Oct 4, 2019 at 0:07

1 Answer 1

10

(Copied from my answer on Super User.SE.)

When you start the service manually from the command line (without using the nohupprefix command or the & suffix to run it in the background, or in other words, just run the command you would put on the ExecStart= line of the .service file), what happens?

a) If the service starts and keeps running, and the prompt does not return until you press Control-C or stop the service in some other way: then Type = simple is the right choice.

b) If the prompt returns but the service keeps running in the background (i.e. the service daemonizes itself on its own), then Type = forking is the right choice.

c) If the service does its job and returns to the prompt without leaving anything running (i.e. the service just adjusts some kernel settings, sends a command to something else or does something similar), then Type = oneshot is probably the right choice. In this case, ExecStart of the service might be the command to "set" something, and ExecStop would be the corresponding command to "unset" it. This type usually benefits of RemainAfterExit=true, so systemd will keep track of the "state" of this service according to whether the thing was most recently "set" or "unset".

The other Type values are special cases. For example, if the service utilizes a D-Bus connection, then Type = dbus might be the best choice. It makes systemd aware of the fact, and then systemd will track this service (and anything that depends on it) by the presence of this service on the D-Bus.

To use Type = notify, the process must be able to connect to Unix socket specified in environment variable $NOTIFY_SOCKET and to report its status by writing messages to that socket whenever necessary. Also, the service file should specify the NotifyAccess option to grant access to the notification socket as appropriate.

There is a command-line utility systemd-notify and a C library function sd_notify(3) you may use to send these messages, but if neither of those is suitable to your requirements, you can just implement your own message sender. The messages required are very simple, and look like shell variable assignments: for example, to notify that the service has successfully completed startup and is ready to serve any incoming requests, the service should send the string equivalent to the output of printf "READY=1\n" to the socket. See man 3 sd_notify for more details on the recognized messages.

Note: many service applications designed to be portable to many Unix-style systems may behave as b) by default, but can be made to work like a) by adding an option (usually described as "don't fork", "keep running in foreground", "don't daemonize" or similar). In that case, if the option has no other side effects, then adding the option and using the a)-type behavior would be preferable for systemd.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.