I decided that I'll dig down into init systems in Linux and learn more about them. I'm running Ubuntu 16.04, so this might look different on other distributions.
The init system in Linux is mainly responsible for starting essential service processes, mounting file systems and possibly other tasks. The main init systems are systemd, System V init and Upstart. Ubuntu uses systemd.
The init system starts after the Kernel starts its first user space process - init. Indeed, let's see what's running with PID 1:
$ ps 1 PID TTY STAT TIME COMMAND 1 ? Ss 0:04 /sbin/init splash
/sbin/init. Let's see what this file is:
$ ls -l /sbin/init lrwxrwxrwx 1 root root 20 Sep 28 18:40 /sbin/init -> /lib/systemd/systemd
From this output, we can figure out that Ubuntu is using systemd. systemd is a fairly new project (initial release was 6 years ago), but it looks like its widely adopted now. systemd would take care of running various services like your ssh server, your web server and various other ones which are more "under the hood" oriented.
systemd organizes itself with unit files which contain the description of various units and their dependencies. The units are organized in configuration files, which live in various directories. The main directories are:
- System unit directory:
/usr/lib/systemd/. Your distribution maintains this, so don't edit it.
- System configuration directory:
/etc/systemd. Make your local changes here.
Well, these are not all directories that contain unit files. Here's the full set of paths that systemd uses:
$ systemctl -p UnitPath show UnitPath=/etc/systemd/system /run/systemd/system /run/systemd/generator /usr/local/lib/systemd/system /lib/systemd/system /usr/lib/systemd/system /run/systemd/generator.late
I won't go into details about what the unit files contain, but instead look at two services that I was curious about - ssh and apache. Who runs them? When are they run? How can I verify that they are running?
Let's start with ssh. The main command to interface with systemd is
systemctl. We can use it to list all services that are running, by calling
systemctl list-units. Let's look for ssh in here:
$ systemctl list-units | grep ssh ssh.service loaded active running OpenBSD Secure Shell server
Indeed, we have ssh running. Now, let's look at its status and its config file.
$ systemctl status ssh ● ssh.service - OpenBSD Secure Shell server Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled) Active: active (running) since Thu 2017-02-09 19:27:57 PST; 4 days ago Main PID: 786 (sshd) Tasks: 1 Memory: 6.4M CPU: 199ms CGroup: /system.slice/ssh.service └─786 /usr/sbin/sshd -D Feb 12 18:23:50 virtbox sshd: Accepted password for petko from 192.168.1.86 port 57805 ssh2 Feb 12 18:23:50 virtbox sshd: pam_unix(sshd:session): session opened for user petko by (uid=0) ...
So here it is. The ssh service is running as process 786. We can see that this process is listening on port 22:
$ sudo netstat -tulpn | grep 786 tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 786/sshd tcp6 0 0 :::22 :::* LISTEN 786/sshd
Indeed, it is.
systemctl has another useful command that allows us to print the configuration file for a unit. It works like this:
$ systemctl cat ssh # /lib/systemd/system/ssh.service [Unit] Description=OpenBSD Secure Shell server After=network.target auditd.service ConditionPathExists=!/etc/ssh/sshd_not_to_be_run [Service] EnvironmentFile=-/etc/default/ssh ExecStart=/usr/sbin/sshd -D $SSHD_OPTS ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure RestartPreventExitStatus=255 Type=notify [Install] WantedBy=multi-user.target Alias=sshd.service
So here you can see where is the configuration file located.
Alright, enough ssh. Let's move on to apache. First, a little history though. Before systemd, apparently the main init system in Linux was System V. System V is different than systemd, because it executes services in sequential order, while systemd can be parallel. System V also can't start services on "as-needed" basis. So I guess that's why systemd was implemented. systemd has its config files in
/etc/init.d. That's where Apache installs its command files as well - it doesn't create systemd unit files. However, systemd knows how to execute the System V init files. I won't go into details of how System V init works, but basically it executes commands on different runlevels and at each runlevel they are executed in sequential order.
Let's see how apache looks like in systemd:
$ systemctl list-units | grep apache apache2.service loaded active running LSB: Apache2 web server
It's running. Now let's get its status:
$ systemctl status apache2 ● apache2.service - LSB: Apache2 web server Loaded: loaded (/etc/init.d/apache2; bad; vendor preset: enabled) Drop-In: /lib/systemd/system/apache2.service.d └─apache2-systemd.conf Active: active (running) since Mon 2017-02-13 12:49:55 PST; 8h ago Docs: man:systemd-sysv-generator(8) Tasks: 55 Memory: 6.5M CPU: 17.042s CGroup: /system.slice/apache2.service ├─9097 /usr/sbin/apache2 -k start ├─9100 /usr/sbin/apache2 -k start └─9101 /usr/sbin/apache2 -k start Feb 13 12:49:54 virtbox systemd: Starting LSB: Apache2 web server... Feb 13 12:49:54 virtbox apache2: * Starting Apache httpd web server apache2 Feb 13 12:49:54 virtbox apache2: AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globall Feb 13 12:49:55 virtbox apache2: * Feb 13 12:49:55 virtbox systemd: Started LSB: Apache2 web server.
Look at something interesting here. The file responsible for starting apache is listed as
/etc/init.d/apache2. That's the file indeed. It's adapted into systemd by using the
systemd-sysv-generator. So that is systemd running. We can run a cat to see that:
$ systemctl cat apache2 # /run/systemd/generator.late/apache2.service # Automatically generated by systemd-sysv-generator [Unit] Documentation=man:systemd-sysv-generator(8) SourcePath=/etc/init.d/apache2 Description=LSB: Apache2 web server Before=multi-user.target Before=multi-user.target Before=multi-user.target Before=graphical.target Before=shutdown.target After=local-fs.target After=remote-fs.target After=network-online.target After=systemd-journald-dev-log.socket After=nss-lookup.target Wants=network-online.target Conflicts=shutdown.target [Service] Type=forking Restart=no TimeoutSec=5min IgnoreSIGPIPE=no KillMode=process GuessMainPID=no RemainAfterExit=yes ExecStart=/etc/init.d/apache2 start ExecStop=/etc/init.d/apache2 stop ExecReload=/etc/init.d/apache2 reload # /lib/systemd/system/apache2.service.d/apache2-systemd.conf [Service] Type=forking RemainAfterExit=no
This is the file that systemd created in order to integrate the System V init command into its system.
What are some other interesting systemctl commands? Let's list them:
# Start / stop /restart a service. $ sudo systemctl restart apache2 # List all services: $ systemctl list-units --type=service # List dependencies: $ systemctl list-dependencies sshd.service # See low level properties of a unit: $ systemctl show sshd.service
And one last cool command:
$ systemd-analyze Startup finished in 3.989s (kernel) + 7.673s (userspace) = 11.663s
This command prints the time it took to startup our system.
So that's all for today. There's definitely more to explore in systemd land - the syntax of unit files, how systemd executes them and so on. I'll leave that for some other time.