Init System: Explanation & Insights

The first process the Linux kernel starts at boot; it launches and supervises all other services and stays running until shutdown.

What It Is

When you power on a Linux server, two things happen in sequence. First the kernel loads: it probes the hardware, mounts the root filesystem, sets up memory and the CPU, and gets the machine into a state where it can run actual programs. Then — and this is the moment that matters — the kernel does something it does exactly once in the entire life of the system: it reaches into userspace, picks one program, starts it, and hands it the keys. That program is the init system, and from that instant everything else on the machine is its child, grandchild, or more distant descendant.

That one program runs as process number one. Its PID is 1, always, on every Linux box that has ever booted. You can see it for yourself:

ps -p 1 -o pid,comm
  PID COMMAND
    1 systemd

On most servers today that name is systemd. On an old box it might say init. Whatever it's called, it is the trunk of the process tree — the thing every other program ultimately grows out of. An init system has three jobs, and they map neatly onto the life of the machine: bring the system up (start every service the box needs, in the right order), keep it running (supervise those services, restart the ones that crash, and adopt orphaned processes so nothing leaks), and bring it down cleanly (stop everything in reverse on shutdown). It is the conductor of the whole orchestra, and it never leaves the stage.

This page teaches the concept from the ground up: what PID 1 really is and why the kernel treats it as sacred, what an init system actually does between boot and shutdown, and the family tree — sysvinit to upstart to systemd — that explains why your server boots the way it does. By the end you'll understand the one process the machine genuinely cannot live without.

PID 1: The One Process the Kernel Can't Live Without

Here is the thing every tutorial leaves muddy, and it's worth nailing once and for all.

The Linux kernel is not a program in the usual sense. It doesn't have a main() you can point at and say "that's the OS running." It's a body of code that the CPU jumps into when hardware needs attention or a process asks for something — and the rest of the time it's dormant, waiting. The kernel needs something in userspace to be alive and in charge: a process to start the services, to be the parent of the process tree, to be there when a child dies. So at the very end of boot, the kernel launches exactly one userspace process and assigns it PID 1. Just one. Not a pool, not a fallback — one.

And PID 1 is special in ways no other process is:

  • It cannot be killed by accident. The kernel ignores the usual fatal signals (like SIGTERM and SIGKILL) sent to PID 1 unless PID 1 has explicitly installed a handler for them. You cannot kill -9 1 your way to disaster from a fat-fingered command. Try it — nothing happens.
  • If it dies anyway, the kernel panics. This is the load-bearing fact. Should PID 1 ever actually exit or crash, the kernel has no parent for the process tree, no one to reap orphans, no one in charge of userspace — and it gives up on the spot with a kernel panic: Attempted to kill init! exitcode=0x.... The machine halts. That's not a bug; it's the kernel saying "the one thing I depended on is gone, and there is no recovering from that." PID 1 is, quite literally, the process the system is built around.
  • Everything descends from it. Walk the process tree all the way up with pstree and every branch terminates at PID 1. Your web server, your database, your shell, the cron daemon firing jobs at midnight — trace any of them upward and you arrive at process 1.

Note

Inside a container, PID 1 is a different story — it's the container's main process, not the host's init, and the host kernel still panics only if the host's PID 1 dies. This is why a container that runs a bare app as PID 1 (with no init-like reaping) can accumulate zombie processes: the app was never written to be PID 1 and doesn't do PID 1's housekeeping. Tools like tini exist precisely to be a tiny, well-behaved PID 1 inside a container.

So when people say "the OS," the part that's always running and in charge in userspace is this one process. The kernel is the law; PID 1 is the government.

What an Init System Actually Does

The three jobs again, now with the detail that makes them real.

It is the first userspace process. Because it's PID 1, it runs before anything else you'd recognize — before the network is up, before any service starts, before you can log in. Everything the running system offers, it offers because PID 1 set it in motion. The init system is the bootstrap: the kernel can't start your database directly (it doesn't know or care what a database is), so it starts the one process whose entire job is to know what should run and start it.

It brings the system up. A modern server runs dozens of background programs — a web server, a database, an SSH daemon, a logging daemon, time sync, and more. Each of these is a service (sometimes called a daemon), and most of them have dependencies: the database should be up before the web app that needs it; the network should be configured before anything that listens on a socket. The init system's job is to know all of this and start everything in a sensible order. How it figures out that order is the whole story of the family tree below — and it's where each generation of init system either shone or stumbled.

It supervises and reaps. Once the system is up, the init system doesn't go to sleep. It watches the services it started. If one crashes, a good init system restarts it (this is supervision, and it's why you should run long-lived programs as proper units instead of launching them with nohup and hoping — more on that under systemd). And it performs a quieter, essential duty: reaping orphans.

Here's what that means. When a process exits, it doesn't vanish immediately — it becomes a zombie, a tiny husk holding just its exit status, waiting for its parent to call wait() and collect that status. Normally the parent does this promptly and the zombie disappears. But what if the parent dies first, leaving children still running? Those children are now orphans. The kernel immediately re-parents every orphan to PID 1. And PID 1, being a proper init system, calls wait() in a loop forever, harvesting the exit status of every orphan that finishes and letting the kernel free its PID. Without this, dead processes would pile up as zombies until the system ran out of process slots. PID 1 is the universal next-of-kin: when your parent dies, init adopts you, and when you die, init buries you. Computing is rarely this tidy a metaphor, so enjoy it while it lasts.

It brings the system down. On shutdown or reboot, the init system runs the whole startup in reverse — stopping services in dependency order, unmounting filesystems, syncing disks — so the box goes down clean instead of being yanked.

The Family Tree

There have been three major init systems in mainstream Linux, and they tell a clean evolutionary story: each one solved the previous one's biggest weakness and introduced the next era's debate.

sysvinit — The Classic

For most of Linux's first two decades, init meant sysvinit (System V init), inherited from the Unix that came before. Its model is plain and legible: a set of numbered runlevels (single-user, multi-user, graphical, reboot…) and a pile of shell scripts in /etc/init.d that start and stop each service. Booting meant running those scripts one after another, in alphanumeric order, and waiting for each to finish before starting the next.

Easy to understand, easy to debug — it's just shell scripts you can read. But two flaws got worse as servers got busier: it ran sequentially (a service that took ten seconds to start blocked everything behind it, so boots crawled), and it was dependency-blind (the order came from numeric prefixes in filenames like S20, S30 — a fragile, manual ordering with no real understanding of "this needs that first"). On a desktop or a small box, fine. On a fleet of servers where boot time and reliability matter, painful. See sysvinit for the full picture.

upstart — The Event-Driven Bridge

Ubuntu hit the sequential-boot wall first and, around 2006, built upstart: an event-driven init that could start services in parallel and react to events ("the network came up," "a disk was plugged in") rather than marching down a fixed list. It was a real step forward and shipped as the default in Ubuntu and even RHEL 6 for years.

But upstart's event model turned out to be awkward to express real dependencies in, and while it was maturing, a more ambitious project overtook it. Today upstart is effectively dead — you'll only meet it on very old Ubuntu boxes. It's the honorable middle child: it proved parallel, event-aware boot was possible and necessary, then lost the field to the system that did it better. See upstart for why it existed and why it faded.

systemd — The Modern Standard

systemd, starting around 2010, won — and on any current server, init means systemd. Instead of events or filename ordering, you declare each service in a small unit file with its dependencies stated explicitly (After=, Requires=, Wants=), and systemd builds a dependency graph and starts everything as parallel as that graph allows. It absorbed jobs that used to be separate programs — logging, scheduling, device management, mounts — which made it powerful and, to its critics, sprawling. It replaced runlevels with named targets (multi-user.target, graphical.target), and you drive the whole thing with systemctl and read its logs with journalctl.

The systemd debate was loud and occasionally bitter, but the outcome is settled: Debian, Ubuntu, RHEL, Fedora, SUSE, and Arch all ship systemd by default. The full deep dive lives on the systemd page.

The Opinion, Plainly

On any server you stand up today, the answer is systemd. Not because it's beyond criticism — it isn't — but because it's what every mainstream distribution ships, what every tutorial assumes, and what your future self (and your colleagues) will expect to find. Run your long-lived programs as systemd units, let it supervise and restart them, and read their logs with journalctl.

Why care about the older ones at all, then? Two reasons, and they're real:

  • Old tutorials and forum answers. A huge amount of the Linux documentation on the internet predates systemd. When a guide tells you to drop a script in /etc/init.d or change your runlevel, you need to recognize what era it's from and translate to the systemd equivalent. Knowing the history is how you read the old maps without getting lost.
  • Legacy boxes. Somewhere in every long-lived organization is a server too important and too scary to touch, running an ancient distribution with sysvinit or upstart. When you finally have to log into it, you'll be glad you know the old commands.

Know the old systems so you can read them. Don't deploy them new.

How I Inspect It

A handful of moves tell you which init system you're on and what it's doing.

# Who is PID 1? (the fastest "which init am I on" check)
ps -p 1 -o comm=

# The whole process tree, rooted at PID 1
pstree -p

# On a systemd box: every service and its state
systemctl list-units --type=service

# Watch a single service
systemctl status nginx.service

The first command is the one I run on an unfamiliar box. If ps -p 1 -o comm= prints systemd, I'm in modern territory and reach for systemctl and journalctl. If it prints init, I'm on something old and switch mental gears to sysvinit (or upstart) — /etc/init.d, the service command, and runlevels.

Pro Tip

On a systemd box, systemd-analyze blame lists every service ranked by how long it took to start at the last boot. It's the single best way to find out why a server is slow to come up — and a small, satisfying demonstration of why "boot in parallel and measure it" beat "run scripts in a row and hope."

Cheat Sheet

# --- Identify ---
ps -p 1 -o comm=                 # name of PID 1 — your init system
cat /proc/1/comm                 # same answer, straight from /proc
pstree -p 1                      # the full descent from PID 1

# --- systemd (modern) ---
systemctl status <svc>           # is a service running? why did it stop?
systemctl start|stop|restart <svc>
systemctl enable|disable <svc>   # start at boot, or not
systemctl list-units --type=service
journalctl -u <svc>              # that service's logs
systemctl get-default            # the boot target (≈ default runlevel)
systemd-analyze blame            # what slowed the last boot

# --- sysvinit / upstart (legacy) ---
service <svc> status|start|stop  # works on both old and new (a shim on systemd)
ls /etc/init.d/                  # the classic service scripts
runlevel                         # current + previous runlevel
telinit 3                        # switch runlevel

The service command is the friendly bridge: it works on sysvinit, on upstart, and on systemd (where it's a thin shim that calls systemctl). When you're not sure what's underneath, service nginx status is a safe first reach.

Why It Matters

The init system is invisible right up until it isn't. When your server boots fine, you never think about PID 1. But the moment a service won't start, or starts in the wrong order, or crashes and doesn't come back, or the box takes four minutes to boot — every one of those is an init-system question. Knowing what PID 1 is, what it's responsible for, and which generation you're talking to turns those incidents from mysteries into checklists. It's also the foundation under a lot of other concepts: a daemon is a long-running process the init system supervises; a service is the init system's unit of "a thing that should be running"; systemctl is just how you talk to it. Get the trunk right and the branches make sense.

See Also

  • systemd — the modern init system you'll actually run
  • sysvinit — the classic shell-script init it replaced
  • upstart — the event-driven bridge between the two
  • runlevel — the old "what state should the box be in" concept
  • process — what PID 1 is the root of
  • pid — the number, and why 1 is sacred
  • daemon — the long-running services init supervises
  • service — init's unit of "something that should be running"
  • systemctl — the command you drive a modern init with
  • journalctl — where a modern init keeps the logs

Is the one process your server can't live without doing its job?

CleverUptime reads /proc to see which services PID 1 has actually got running, and flags the moment one that should be up has quietly stopped — so you hear it from a dashboard, not from a customer.

Want to see your own server's health right now? One command, no signup, no install.

Check your server →