Unix and Linux startup scripts Part 4, Systemd

This is a continuation of Unix and Linux startup scripts, Part 3

Systemd is gaining favor in Linux distributions. This is a big change from inittab and everything else we've had in the past. To find out more about it, I downloaded the latest Ubuntu desktop and began exploring. The first thing I noticed is that there is still an init.d directory and it does have shell scripts in it. However, /sbin/init is now a symlink to /etc/systemd and those scripts do not execute when systemd is in charge.

Systemd is the default on Ubuntu 15.04

Note that the Advanced Options section of the Grub menu will let you boot with Upstart. You'll need to edit your /etc/default/grub file to put a "#" ahead of GRUB_HIDDEN_TIMEOUT=0 and do a "sudo update-grub" to have that option.

As systemd certainly can execute shell scripts, I wondered if it might be piggybacking these. It isn't: I modified /etc/init.d/rc.local to add "date >> /home/tony/booted". That runs if I boot with Upstart, but not with systemd. So how would you do something simple like that?

Systemd has its own directory, /etc/systemd. There are various files and sub-directories. In the sub-directories are the "service" files (called units in much documentation) that control startup. I noticed a "user" directory and figured that might be a good place to add my own little test, but apparently it isn't necessarily. See systemd/User. So I created it in my home directory.

[Unit]
Description=Tony's date stamper

[Service]
ExecStart=/home/tony/tonyapp

[Install]
WantedBy=multi-user.target
 

The Description will appear in logs. The ExecStart is what I want to happen and WantedBy tells it when. There are other possible targets: poweroff.target (when system is going down, like run-level 0), rescue.target (single user, init 1), multi-user.target (init 2-4), graphical.target (init 5) and reboot.target (init 6). ExecStart could be a binary, a shell script - but note that you must include the full path and that the environment is empty - no variables are set. If you must set variables, add an EnvironmentFile= line pointing at something that sets them or use Environment="XYZ=7" 'YY=hello there' for simple cases. After adding this file, I enabled it with "sudo systemctl enable /home/tony/tonyapp.service". I could force it to run right now with "systemctl start tonyapp".

Note that this won't try to restart because there is nothing in the service file to say that it should. There are many, many other control words you can use. You can specify that other services must start before this and that others must be after. Service files can be quite complex; you can learn more by looking in the /etc/systemd/system directory. You can ask about the status of any service with (for example):

$ systemctl status tonyapp
● tonyapp.service - Tony's date stamper
   Loaded: loaded (/home/tony/tonyapp.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Tue 2015-05-12 06:56:36 PDT; 10min ago
  Process: 1417 ExecStart=/home/tony/tonyapp (code=exited, status=0/SUCCESS)
 Main PID: 1417 (code=exited, status=0/SUCCESS)

May 12 06:56:36 ubuntu systemd[1]: Started Tony's date stamper.
May 12 06:56:36 ubuntu systemd[1]: Starting Tony's date stamper...
 

That tells us everything we'd need to know! Other services may give even more information:

$ systemctl status sshd
● ssh.service - OpenBSD Secure Shell server
   Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2015-05-12 06:50:56 PDT; 17min ago
  Process: 955 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
 Main PID: 708 (sshd)
   CGroup: /system.slice/ssh.service
           └─708 /usr/sbin/sshd -D

May 12 06:50:56 ubuntu systemd[1]: Started OpenBSD Secure Shell server.
May 12 06:50:56 ubuntu systemd[1]: Starting OpenBSD Secure Shell server...
May 12 06:50:57 ubuntu sshd[708]: Server listening on 0.0.0.0 port 22.
May 12 06:50:57 ubuntu sshd[708]: Server listening on :: port 22.
May 12 06:50:57 ubuntu sshd[708]: Received SIGHUP; restarting.
May 12 06:50:57 ubuntu systemd[1]: Reloaded OpenBSD Secure Shell server.
May 12 06:50:57 ubuntu sshd[708]: Server listening on 0.0.0.0 port 22.
May 12 06:50:57 ubuntu sshd[708]: Server listening on :: port 22.
May 12 06:52:56 ubuntu sshd[1283]: Accepted password for tony from 10.211.55.2 port 58485 ssh2
May 12 06:52:56 ubuntu sshd[1283]: pam_unix(sshd:session): session opened for user tony by (uid=0)
 

You can get a simple status list with "systemctl list-unit-files --type=service"

Service status

Note the STATE column. Possible states are:

  • enabled
  • disabled
  • static - enabled if something else wants it, disabled otherwise. Its unit file does not contain an "install" section.
  • masked - disabled and cannot be started. "systemctl mask tonyapp.service" would prevent it starting, "systemctl unmask tonyapp.service" restores normalcy
  • linked - Came from a symlink to the unit file by "systemctl link SOMEUNITFILE". The unit file is now available for start and other commands although it is not installed directly in the unit search path.
  • failed
  • enabled-runtime - enabled for only this boot of the system
  • linked-runtime - linked for only this boot of the system
  • masked-runtime - masked for only this boot of the system
  • indirect - Unit file itself is not enabled, but it has a non-empty Also= setting in the "[Install]" section. That keyword allows units to be treated as a set.

That "masked" seems to be done by symlinking to /dev/null.

So could you use SysV init scripts? Yes, but with some caveats: Compatibility with SysV. Unlike SysV, scripts cannot hang. By default, they are stopped in 5 minutes (can be changed with TimeoutStopSec= or in sysytemd conf files). Let me mention again that the environment is clean - nothing set at all. Also, systemd won't try to stop a service that is not already running.

By the way, your unit file specifies how things are stopped with KillMode= and a few other directives.

Switching to targets is easy: "systemctl isolate rescue.target". In addition to that, systemctl takes arguments like "reboot", "default", "suspend", "hibernate" and more.

Systemd can also start things when other things happens. It functions as the (x)inetd super daemon did for network connections. It can start a service when a file is created and much more. I have barely scratched the surface here.

I like systemd. I learned BSD init and SysV inittab thirty-five years ago, but I see no need to be stubborn about it: this is better. I didn't like Upstart or any of the other replacement wanna-be's, but systemd makes sense.

It's optional for now, but Linux Mint expects to switch to systemd next year

Grab your pitchforks: Ubuntu to switch to systemd on Monday



Got something to add? Send me email.





(OLDER) <- More Stuff -> (NEWER)    (NEWEST)   

Printer Friendly Version

-> -> Unix and Linux startup scripts Part 4, Systemd




Increase ad revenue 50-250% with Ezoic


More Articles by

Find me on Google+

© Anthony Lawrence



Kerio Samepage


Have you tried Searching this site?

Unix/Linux/Mac OS X support by phone, email or on-site: Support Rates

This is a Unix/Linux resource website. It contains technical articles about Unix, Linux and general computing related subjects, opinion, news, help files, how-to's, tutorials and more.

Contact us





It is the the duty of a Webmaster to allocate URIs which you will be able to stand by in 2 years, in 20 years, in 200 years. (Tim Berners-Lee)

Any teacher that can be replaced with a computer, deserves to be (David Thornburg)








This post tagged: