systemd vs sysvinit part 2

Tags: systemctl, linux, systemd
Publish Date: 2016-05-15

For a quick and dirty cheatsheet, see my other post

Differences between systemd and sysvinit (a.k.a init) - Part 2

In part 1 of this article, I have provided an overview of how sysvinit boots up and manages services. Here in part 2, I will show how this has changed with systemd.


Systemd - Boot Process

While in sysvinit there is a concept of runlevels, systemd is based on targets.

The idea behind a target is that a collection of units have to be activated when the system reaches a certain target. You can see the activation of units like dependencies for targets.

A target could be something like the old runlevels (e.g., but it could also be something like hardware or network detection (e.g. A unit could be something like a service, mount, socket etc., but a target itself is also a unit.

So you can interpret this as: "Make sure that certain services, mounts, sockets etc are activated when my system reaches a certain state."

For a list of units in systemd see systemctl -t help

[root@10 system]# systemctl -t help
Available unit types:

During the boot process, the first process (pid 1) is (/lib/systemd/)systemd. In fact, you will see that the old /sbin/init is a symlink to /lib/systemd/systemd

[root@10 system]# ls -l /sbin/ | grep systemd
lrwxrwxrwx. 1 root root       22 Jul 14  2015 init -> ../lib/systemd/systemd

Since systemd is no longer based on runlevels, it has gotten rid of the /etc/inittab file, where the default runlevel used to be defined. Instead, systemd finds its default target through /etc/systemd/system/

[root@10 system]# ls -l /etc/systemd/system
total 4
drwxr-xr-x. 2 root root   54 Jul 14  2015
lrwxrwxrwx. 1 root root   41 Jul 14  2015 dbus-org.fedoraproject.FirewallD1.service -> /usr/lib/systemd/system/firewalld.service
lrwxrwxrwx. 1 root root   46 Jul 14  2015 dbus-org.freedesktop.NetworkManager.service -> /usr/lib/systemd/system/NetworkManager.service
lrwxrwxrwx. 1 root root   57 Jul 14  2015 dbus-org.freedesktop.nm-dispatcher.service -> /usr/lib/systemd/system/NetworkManager-dispatcher.service
lrwxrwxrwx  1 root root   41 May 13 11:21 -> /usr/lib/systemd/system/
drwxr-xr-x. 2 root root   85 Jul 14  2015
drwxr-xr-x. 2 root root   31 Jul 14  2015
drwxr-xr-x. 2 root root 4096 Apr  6 09:45
drwxr-xr-x. 2 root root   49 Jul 14  2015
drwxr-xr-x. 2 root root   59 Jul 14  2015
drwxr-xr-x. 2 root root   43 Jul 14  2015

As you can see, my is symlinked to Which is a bit comparable to the old runlevel 3.

We can get and set the default runlevel with systemctl set-default and systemctl get-default

[root@10 system]# systemctl get-default
[root@10 system]# systemctl set-default
rm '/etc/systemd/system/'
ln -s '/usr/lib/systemd/system/' '/etc/systemd/system/'

For simplicity's sake, let's assume that I have set my default target back to If we take a look at the file, we will see the following:

[root@10 system]# cat /usr/lib/systemd/system/

Description=Multi-User System
Conflicts=rescue.service rescue.service

[Install] means that all units within the directories (more on the .wants directories later) must be activated first before the current unit ( can be activated. So for now, the control is handed over to, which in its turn requires

In, there is no Requires= directive specified, but it does have a Wants= directive.

The Wants= directive lists the units that the current unit will try to activate. However, if these units fail to be activated, it won't stop the current unit (in this case from being activated.

What systemd will do at this point, is to look for .wants directories under /etc/systemd/system/ and (/usr)/lib/systemd/system/ (more on their differences later) with the name of the the specified target. In this case, it finds /usr/lib/systemd/system/ and activates the units within that directory.

From that point, the control is passed back up the chain again. First back to and activates units within in both /etc/systemd/system and (/usr)/lib/systemd/system directories, then the same for and finally back to A great way to visualize how control has been passed from one target to another and which units have been activated in the process, is to use systemctl list-dependencies <>

It is important to note that services in systemd are activated in a parallel manner, whereas in sysvinit was done sequentially (by the number of K- and S- scripts in runlevel directories).

Another note of importance is that there is a difference between the .wants directories in /etc/systemd/system/ and (/usr)/lib/systemd/system/. While the .wants directories in the former is setup by the system and should never be touched by users, the .wants directories in the latter allow the user to manage his own dependencies. This becomes obvious when you enable / disable services to be run upon boot.

Systemd - Enable service at startup

When you install a service (such as nginx in this example), your package manager will create a .service file in the /usr/lib/systemd/system/ directory.

[root@10 vagrant]# ls /usr/lib/systemd/system | grep nginx

To make sure that a service is enabled upon boot, you can use the systemctl enable command:

[root@10 vagrant]# systemctl enable nginx
ln -s '/usr/lib/systemd/system/nginx.service' '/etc/systemd/system/'

What we can see above, is that the systemctl enable command actually creates a symlink from the .wants directory of our default target (in our case multi-user.wants) to /usr/lib/systemd/system/ for our service. In a way a bit comparable to how the scripts in runlevel directories (/etc/rc{number}.d/) in sysvinint were symlinked to scripts in /etc/init.d/.

You can also use systemctl disable <service> to disable a service. In that case, the previously created symlink will be removed.

Systemd - start / stop services

In sysvinit, there were different commands for managing services at startup (chkconfig) and for running/stopping services (service). In systemd, that is all controlled by the systemctl command.

To start a service, use systemctl start <service>

[root@10 vagrant]# systemctl start nginx
[root@10 vagrant]# systemctl status nginx
nginx.service - nginx - high performance web server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled)
   Active: active (running) since Sun 2016-05-15 14:35:07 UTC; 2s ago
  Process: 2735 ExecStop=/bin/kill -s QUIT $MAINPID (code=exited, status=0/SUCCESS)
  Process: 2744 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)
  Process: 2743 ExecStartPre=/usr/sbin/nginx -t -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)
 Main PID: 2747 (nginx)
   CGroup: /system.slice/nginx.service
           ├─2747 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
           └─2748 nginx: worker process

Systemd - Change targets

In sysvinit, a sys-admin might have to change runlevel to perform administrative tasks. In systemd, since there are no runlevels anymore, you will have to change target:

[root@10 system]# systemctl isolate
[root@10 system]# who -r
[root@10 system]# runlevel
3 1 # indicates that the current runlevel is 1 and previous runlevel is 3

Ironically enough, to get the current target, you would still use the old who -r and runlevel commands.

systemd vs sysvinit part 1

Tags: runlevel, sysvinit, linux
Publish Date: 2016-05-13

For a quick and dirty cheatsheet, see my other post

Differences between systemd and sysvinit (a.k.a init) - Part 1

During your system startup, once your boot-loader (e.g. grub) has finished loading the kernel and ram-disk, it will handover control to a "service manager" to make sure that certain services / daemons are running. systemd and sysvinit are those "service managers".

While sysvinit (or simply init) has been around for a long time, the recent Linux distro's (from Debian 7, RedHat / CentOs 7, Ubntu 15 and CoreOS) have adopted the systemd approach. 

Here in part 1, I will give an overview of how the system starts up and how the services are managed in sysvinit. In part 2, I will give an overview of how this has changed with systemd.


SysVInit - Boot process

In sysvinit, there is a concept of runlevel. A runlevel is a mode in which your system operates, such as 3 = full multiuser-mode, 5 = graphical mode etc.. Just think of it like the "Windows safe mode" being different from the normal mode, where the safe mode will have less features / programs available to you than the normal mode.

You can find the runlevels in /etc/inittab. That is also where you can set a default runlevel. In my case, I see the following line at the bottom of my file:


This indicates that my default runlevel is 3 (Multiuser mode with networking). That would also be the case for most servers.

Every runlevel has its own directory, such as /etc/rc3.d/ (for runlevel 3). If you look at the files in these directories, they all start with either K or S, followed by a number, then by the name of a service, e.g. S64mysqld. Apart from that, they are all symlinks to scripts in /etc/init.d/, where scripts reside to start/stop/restart/reload your services. The numbers in these filenames represent the order in which these scripts get executed. Here is a selection of files (symlinks) that I have in /etc/rc3.d

[root@vagrant-centos64 vagrant]# ls /etc/rc3.d/
lrwxrwxrwx.  1 root root   19 Oct 30  2013 K10saslauthd -> ../init.d/saslauthd
lrwxrwxrwx.  1 root root   18 Oct 30  2013 K15svnserve -> ../init.d/svnserve
lrwxrwxrwx.  1 root root   17 Oct 30  2013 K30postfix -> ../init.d/postfix
lrwxrwxrwx.  1 root root   20 Oct 30  2013 K50netconsole -> ../init.d/netconsole
lrwxrwxrwx   1 root root   13 Jan 18  2014 K60nfs -> ../init.d/nfs
lrwxrwxrwx   1 root root   20 Jan 18  2014 K69rpcsvcgssd -> ../init.d/rpcsvcgssd
lrwxrwxrwx   1 root root   20 Jan 18  2014 K87multipathd -> ../init.d/multipathd
lrwxrwxrwx.  1 root root   21 Oct 30  2013 K87restorecond -> ../init.d/restorecond
lrwxrwxrwx.  1 root root   15 Oct 30  2013 K89rdisc -> ../init.d/rdisc
lrwxrwxrwx   1 root root   22 Jan 18  2014 S02lvm2-monitor -> ../init.d/lvm2-monitor
lrwxrwxrwx   1 root root   19 Jan 18  2014 S08ip6tables -> ../init.d/ip6tables
lrwxrwxrwx   1 root root   18 Jan 18  2014 S08iptables -> ../init.d/iptables
lrwxrwxrwx   1 root root   17 Jan 18  2014 S10network -> ../init.d/network
lrwxrwxrwx   1 root root   17 Jan 18  2014 S12rsyslog -> ../init.d/rsyslog
lrwxrwxrwx   1 root root   19 Jan 18  2014 S55memcached -> ../init.d/memcached
lrwxrwxrwx   1 root root   14 Jan 18  2014 S55sshd -> ../init.d/sshd
lrwxrwxrwx   1 root root   16 Jan 18  2014 S64mysqld -> ../init.d/mysqld

When your system boots up, the first process (pid 1) is /sbin/init, then it finds the default runlevel in /etc/inittab. Based on that runlevel number, it navigates to the runlevel directory for that number (/etc/rc3.d/ in my case). Once there, it runs the K-scripts with a stop option and then run the S-scripts with a start option. These scripts are run sequentially in the order to which they are numbered. Once it has run all the K- and S-scripts, your system is then ready with all processes running that you need within that runlevel.

SysVInit - Enable service at startup

So you might wonder: "How do these symlinks land in the runlevel directories?" and "What if I want to enable a service at startup?"

In sysvinit, that is done by chkconfig. Let's say you have installed nginx and you want to enable it at startup:

[root@vagrant-centos64 vagrant]# chkconfig nginx on
[root@vagrant-centos64 vagrant]# chkconfig | grep nginx
nginx          	0:off	1:off	2:on	3:on	4:on	5:on	6:off

With the first command, we have enabled nginx at startup. With the second command, we check for which runlevels we have enabled nginx at startup. It shows 2,3,4 and 5. This is the default behaviour for chkconfig <service> on when we leave out the --level option.

If we look at our /etc/rc3.d/ directory, we will see that a S-script has been added for nginx, same for the other directories where nginx has been enabled. However, if we look at the runlevel directories 0,6, for which nginx has been disabled (see output chkconfig above), we will see that a K-script has been created for nginx.

[root@vagrant-centos64 vagrant]# ls -l /etc/rc3.d/ | grep nginx
lrwxrwxrwx  1 root root 15 May 12 11:30 S85nginx -> ../init.d/nginx
[root@vagrant-centos64 vagrant]# ls -l /etc/rc0.d/ | grep nginx
lrwxrwxrwx  1 root root 15 May 12 10:51 K15nginx -> ../init.d/nginx

SysVInit - service command

Please bear in mind that chkconfig is only meant to make sure that certain services are started and stopped when you change into another runlevel, such as when you boot up your system or by telinit. chkconfig does not start a service or stop a service for you on the spot. For that, you need the service command:

[root@vagrant-centos64 vagrant]# service nginx start
Starting nginx:                                            [  OK  ]

SysVInit - Change runlevels

You would hardly ever change the runlevel while your system is running. But as a system administrator, there might be times that you want to switch to the single-user mode (runlevel 1) to perform some administrative tasks. You can change runlevel through the init command (which has pid 1) or through telinit, which tells init to change runlevel. To find the current runlevel, you can use the runlevel command or who -r.

[root@vagrant-centos64 vagrant]# telinit 1
[root@vagrant-centos64 vagrant]# who -r
         run-level 1  2016-05-13 08:36                   last=3

Quick and dirty systemvinit vs systemd vs upstart cheatsheet

Tags: linux, upstart, runlevel, systemctl, service, sysvinit, systemd
Publish Date: 2016-05-13

Quick and dirty cheatsheet





Start a service

service <name> start

systemctl start <name>

service <name> start

Stop a service

service <name> stop

systemctl stop <name>

service <name> stop

Enable service at startup

chkconfig <name> on


chkconfig <name> --level 2,3

systemctl enable <name>

update-rc.d <name> enable


update-rc.d <name> enable 2 3



Disable service at startup

chkconfig <name> off

systemctl disable <name>

update-rc.d <name> disable

Set default runlevel

Edit in /etc/inittab



systemctl set-default <>

Edit in /etc/init/rc-sysinit.conf



Get default runlevel

Read from /etc/inittab



systemctl get-default

Read from


Set current runlevel

init <number>

telinit <number>

systemctl isolate <>

init <number>

telinit <number>

Get current runlevel


who -r


who -r


who -r