What Is sysvinit and How Does It Differ From systemd?
Updated
sysvinit is the traditional Unix System V-style init system: it is the first process the kernel starts (PID 1) and is responsible for bringing the rest of the operating system up. It reads /etc/inittab to decide which runlevel to enter, then runs the scripts in /etc/init.d (linked from runlevel directories such as /etc/rc3.d) in a fixed sequence to start daemons like networking, cron, and syslog. It is a good fit if you want a small, script-driven, predictable boot process, or if you are maintaining older distributions and hardware. It is a poor fit if you need parallel service startup, socket activation, or integrated logging, which is where systemd differs most.
What sysvinit actually does
The init daemon is the first process spawned by the kernel, so it holds PID #1 and is responsible for spawning the other daemons the OS needs to operate — networking, cron, syslog, and so on. sysvinit performs that role in a deliberately simple way:
- Runlevels.
/etc/inittabdefines what each runlevel means (single-user, multi-user, graphical, reboot, shutdown) and which scripts run for each. - Sequential scripts. Each service is a shell script in
/etc/init.d. Symlinks in/etc/rcN.dnamedS##name(start) andK##name(kill) determine order by their numeric prefix. - No built-in supervision. If a daemon crashes, sysvinit does not automatically restart it unless the script or an external tool does so.
- Plain-text logs. Services typically write to syslog or their own files; there is no unified journal.
Because ordering is encoded in filenames and scripts run one after another, boot time grows with the number of services, but the behavior is easy to trace by reading the scripts.
How systemd differs
systemd replaces the script-and-runlevel model with declarative unit files and a central manager. The practical differences:
| Dimension | sysvinit | systemd |
|---|---|---|
| Startup | Sequential shell scripts | Parallel, dependency-ordered units |
| Configuration | /etc/inittab + /etc/init.d scripts |
Unit files (*.service, *.target, etc.) |
| Service dependencies | Ordering via S##/K## prefixes |
Explicit After=, Requires=, Wants= |
| Process supervision | None built in | Restarts, cgroups, resource control |
| Logging | syslog or per-service files | journald journal |
| Activation | Start at boot/runlevel | Also socket, bus, path, timer activation |
| Targets vs runlevels | Runlevels | Targets (e.g. multi-user.target) |
The trade-off is the same one the source frames as the core dispute: systemd claims to be a good and modern replacement for SysVinit, but it concentrates many responsibilities (init, logging, networking, device management) into one project, which is exactly what critics object to.
Alternatives to both
The init landscape is wider than sysvinit vs systemd. The source lists these init daemons, with several marked inactive (no development activity for several years):
- Active: systemd, SysVinit, OpenRC, runit, s6, Shepherd, finit, Hummingbird, superd, 31init, Dinit, procd, dmaster, prometheus
- Inactive: uselessd, Upstart, InitNG, cinit, minit, Epoch
If your goal is simply to avoid systemd, OpenRC, runit, and s6 are the commonly cited replacements; if your goal is minimal change from a classic setup, staying on sysvinit or a compatible script-based init is the smallest step.
Why people move away from systemd
The source's case against systemd is built on a list of notable bugs and security issues rather than on architecture alone. Examples it cites include:
- A Datadog outage costing 5 million dollars caused by a systemd upgrade.
- A widespread Azure outage when systemd 237-3ubuntu10.54 was published to the bionic-security pocket, after which instances could no longer resolve DNS queries, breaking networking.
- CVE-2017-15908 (resolved loop on packets with pseudo DNS types), CVE-2018-15688 (out-of-bounds write in systemd-networkd DHCPv6 option handling), and CVE-2018-16864/16865/16866 (a systemd-journald exploit).
- Operational issues such as PID 1 getting stuck printing "Time has been changed" continuously,
systemctlstatus taking over 10 seconds when the disk journal is used, andsystemctltreating active→failed as a successful operation.
These are the concrete observations behind the general complaint; they are worth reading directly if you are deciding whether the risk profile matters for your systems.
Migrating from systemd to sysvinit: what to watch
There is no in-place switch — you generally choose a distribution or image that ships the init you want, or rebuild the userland around it. When you do, expect these friction points:
- Service definitions don't translate. A
*.serviceunit has no direct sysvinit equivalent; you rewrite it as an/etc/init.dscript withstart,stop,restart, andstatuscases. - Dependencies become ordering.
After=/Requires=must be expressed asS##/K##numbering, which is coarser and easier to get wrong. - No journal. You lose
journalctl; plan for syslog or per-service log files and adjust any tooling that parsed the journal. - No socket/timer activation. Services that relied on systemd socket or timer units need another mechanism (inetd-style activation, cron, or an external supervisor).
- Supervision is your job. If you depended on
Restart=always, add a supervisor or a wrapper loop, or accept that a crashed daemon stays down.
Verify each step by rebooting into the target runlevel and checking that the expected daemons are running and that networking, logging, and cron behave as before.
Choosing between them
Pick sysvinit (or a compatible script-based init) when you want a small, readable, sequential boot process, are working with older or resource-constrained systems, or specifically want to avoid systemd's scope. Pick systemd when you need parallel startup, dependency management, socket/timer activation, cgroup-based resource control, and unified logging out of the box. If neither extreme fits, OpenRC, runit, or s6 sit between them and are the usual destinations for people leaving systemd without returning to classic SysV scripts.