Does systemd still have the concept of runlevels? For example is it pointless to use telinit <number>?

  • 2
    Possible duplicate of Change runlevel with systemd Feb 6, 2019 at 3:28
  • i don't know about the answers below, but in RHEL/Centos 7.6 init 1 or init 3 or init 5 or init 6 or init 0 or runlevel still behave as they always have, and that's all I care about. Much easier syntax then systemctl blabla blabla.blabla
    – ron
    Mar 21, 2019 at 15:24

4 Answers 4


SystemD Run-Level Low-Down

Within the SystemD(aemon), runlevels are exposed as "Targets." The concept is still there, but the workflow to produce the desired result for your requirement is different.

The attached should clarify this issue.

How do I change the current runlevel?

$ systemctl isolate runlevelX.target

How do I change the default runlevel for next-boot?

# Create a symlink
$ ln -sf /usr/lib/systemd/system/multi-user.target /etc/systemd/system/default.target
  • -s creates symbolic link
  • -f removes the existing destination file

OR (as @centimane suggested) simply use the "blessed" systemd command:

systemctl set-default [target name].target

How do I identify the current runlevel?

$ systemctl list-units --type=target
  • Can I still use the init command to switch between runlevels?
    – drpaneas
    Oct 2, 2014 at 15:47
  • 2
    If your systemd package is built with SysV compat support, it will include a telinit symlink to the systemd binary, which, when called as telinit, will map runlevels 0-6 to systemd targets - check telinit(8) for a list of those mappings.
    – Wieland
    Oct 3, 2014 at 7:44
  • 3
    To change the default target you should use systemctl set-default [target name].target rather than manually creating the link.
    – Centimane
    Jan 8, 2018 at 19:16
  • systemctl list-units --type=target does not identify the current runlevel, it lists all the active .target units though. Mar 3 at 2:40

No. As the systemd people themselves wrote twice over, once in their telinit manual and once in their runlevel manual, runlevels are "obsolete". You can forget about runlevels.

These things do not actually exist in systemd at all, outwith a few compatibility shims.

  • There are some symbolic links for target names, but these targets are never actually used by systemd proper.
    • Rather, the bootstrap process employs a default.target (and thence one or both of a graphical.target and a multi-user.target), a rescue.target, or an emergency.target. And the shutdown process involves a shutdown.target, a reboot.target, a halt.target, or a poweroff.target. No run-level targets are involved in either bootstrap or shutdown.
    • The telinit command, which one might think uses the compatibility symbolic links to map its command-line arguments, does not do that either. There's a hardwired table in the source code of the telinit program, and the numbers 2, 3, 4, and 5 as arguments to the command are hardwired to map to multi-user.target and graphical.target.
    • systemd-update-utmp also has an internal hardwired table.
  • There is no "init table" of runlevel stuff. systemd is only compatible with van Smoorenburg rc, not with van Smoorenburg init.
  • There is no "current run level" value maintained by systemd itself. Rather, the almost wholly undocumented systemd-update-utmp command operates internally in terms of the activation states of rescue.target, multi-user.target, and graphical.target.
  • systemd-sysv-generator, systemd's backwards compatibility service unit generator, merges the /etc/rc[234].d directories into just the one Wanted-By relationship to multi-user.target in generated service units. There is no actual reference to run levels in the generated service units. (There used to be, years ago, but the systemd people found that this went wrong, because they weren't being referenced anywhere else.)

If one is a user of a system that builds systemd as did Arch Linux for the questioner at "Why does `init 0` result in "Excess Arguments" on Arch install?", one does not even get the compatibility shims, and commands such as init 0 result in the "native" systemd behaviour, which is to complain that the command has been incorrectly invoked.

Further reading


Thanks very much. So, if I understood correctly:

For example:

ls -ll /usr/lib/systemd/system/runlevel*.target


/usr/lib/systemd/system/runlevel0.target -> poweroff.target
/usr/lib/systemd/system/runlevel1.target -> rescue.target
/usr/lib/systemd/system/runlevel2.target -> multi-user.target
/usr/lib/systemd/system/runlevel3.target -> multi-user.target
/usr/lib/systemd/system/runlevel4.target -> multi-user.target
/usr/lib/systemd/system/runlevel5.target -> graphical.target
/usr/lib/systemd/system/runlevel6.target -> reboot.target

So as you can see, the concept of runlevels do exists, but it is quite obsolete due to the fact that the runlevel.target files are not actually “real” files but soft-links to the new, modern, better named files scheme which systemd likes to call them “targets”.

So, if you would like to do sth like telinit 5 it would be like this: systemctl isolate runlevel5.target which is identical with: systemctl isolate graphical.target (recommended in my opinion).

Just in case you are interested to know all the possible targets:

ls /usr/lib/systemd/system/*.target
  • Yes, I believe that you are understanding this correctly. I will be a late adopter of SystemD, as the procedural, step-step-step, INIT.D system is what I am most familiar with... I applaud that you are exploring SystemD. The best part of SystemD is its parallel multi-threading, which enables faster boot. Multi-Threading boot can be accomplished with INIT.D, but requires strong BASH scripting. Oct 2, 2014 at 16:03
  • BTW, ls -ll is equivalent to ls -l.  You might want to get into the habit of using ls -ld. May 14, 2017 at 5:53
  • telinit 0 / telinit 6 still work. Since this helps with migration, and I think most distros still don't see a reason to drop the support yet. isolate clearly aspired to mimic how run-levels work, but there are various evil edge cases. I highly recommend ignoring all instructions to isolate runlevel5.target or even isolate graphical.target. Example edge case: github.com/systemd/systemd/issues/6505
    – sourcejedi
    Aug 19, 2018 at 14:30

systemd introduced targets as a counterpart for runlevels in sysV init system. sytemd developers made it almost compatible with most of the sysV scripts. Same happens for telinit <runlevel>. This is translated into systemd equivalent.

For example telinit 0 powers off the machine. systemd has poweroff.target to do the same as runlevel 0. So telinit 0 is translated by systemd to activate poweroff.target.

But some compatibility problems are there with sytemd and sysV init systems-> https://www.freedesktop.org/wiki/Software/systemd/Incompatibilities.

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.