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.
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: Started Tony's date stamper. May 12 06:56:36 ubuntu systemd: 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: Started OpenBSD Secure Shell server. May 12 06:50:56 ubuntu systemd: Starting OpenBSD Secure Shell server... May 12 06:50:57 ubuntu sshd: Server listening on 0.0.0.0 port 22. May 12 06:50:57 ubuntu sshd: Server listening on :: port 22. May 12 06:50:57 ubuntu sshd: Received SIGHUP; restarting. May 12 06:50:57 ubuntu systemd: Reloaded OpenBSD Secure Shell server. May 12 06:50:57 ubuntu sshd: Server listening on 0.0.0.0 port 22. May 12 06:50:57 ubuntu sshd: Server listening on :: port 22. May 12 06:52:56 ubuntu sshd: Accepted password for tony from 10.211.55.2 port 58485 ssh2 May 12 06:52:56 ubuntu sshd: 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"
Note the STATE column. Possible states are:
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.
Got something to add? Send me email.
More Articles by Anthony Lawrence © 2015-05-13 Anthony Lawrence
Anyone even peripherally involved with computers agrees that object-oriented programming (OOP) is the wave of the future. Maybe one in 50 of them has actually tried to use OOP – which has a lot to do with its popularity (Steve Steinberg)