Skip to main content

Daemon

A daemon is a background process that runs continuously without a controlling terminal, typically started at boot and providing a service to other processes or the system. Common daemons include sshd (SSH server), nginx (web server), and cron (job scheduler).

What Is a Daemon in Simple Terms

A daemon is a background worker. It starts when the system boots, runs quietly in the background, and waits to do its job. It has no terminal — it is not connected to any user session. It does not stop when you log out.

The name comes from Greek mythology (daemons were helpful spirits that worked invisibly). In Unix, the naming convention is to append 'd' to the service name: sshd (SSH daemon), nginx (the 'd' is implied by convention), cron becomes crond on RedHat systems, postgresql runs as the postgres daemon.

How It Works

Traditional daemons used a "double fork" technique to detach from the terminal. With systemd, this is no longer necessary — systemd manages the process lifecycle directly.

TEXT
Traditional daemon startup (pre-systemd):
1. Fork a child process
2. Parent exits (terminal returns to user)
3. Child calls setsid() -- new session, no controlling terminal
4. Child forks again (optional, prevents reacquiring terminal)
5. Grandchild is the actual daemon
6. Close stdin, redirect stdout/stderr to /dev/null or log file
7. Write PID to /var/run/service.pid
8. Start doing work
Modern systemd daemon startup:
1. Write a [Service] unit file with Type=simple
2. systemd runs ExecStart directly
3. systemd handles PID tracking, logging, restart
4. No double fork needed
5. Logs go to journald automatically

Common production daemons:

Bash
sshd SSH server -- accepts incoming connections
nginx Web server / reverse proxy
apostgres PostgreSQL database server
redis-server Redis cache/database
docker Docker daemon -- manages containers
kubelet Kubernetes node agent
prometheus Metrics collection
journald Log collection (part of systemd)
cron/crond Job scheduler
fail2ban Brute-force protection
auditd Security audit logging

How systemd manages daemon lifecycle:

◈ DIAGRAM
State machine for a daemon:
+----------+
| inactive | Unit is not running
+----------+
|
| systemctl start
v
+----------+
|activating| Starting up
+----------+
|
| started successfully
v
+----------+
| active | Running normally
+----------+
|
| crash or systemctl stop
v
+----+-----+
|deactivate| Stopping
+----------+
|
| Restart=on-failure if crashed
v
+----------+
| inactive | or back to activating
+----------+

Practical Commands

Bash
## List all running daemons (services)
systemctl list-units --type=service --state=running
## See which daemons start at boot
systemctl list-unit-files --type=service --state=enabled
## Check if a daemon is running
systemctl is-active nginx
## active
## Check if a daemon starts at boot
systemctl is-enabled nginx
## enabled
## See daemon resource usage
systemctl status nginx
## shows memory, CPU, PID, and recent logs
## Prevent a daemon from running (mask it)
sudo systemctl mask nginx
## nginx.service is now masked -- cannot be started at all
## even by other services
sudo systemctl unmask nginx
## removes the mask
## See all failed daemons
systemctl list-units --type=service --state=failed
## View daemon logs
journalctl -u nginx -f ## follow live
journalctl -u nginx --since today ## today's logs

Troubleshooting

Symptom Command What to Look For
Daemon not starting journalctl -u name -n 30 Error in startup sequence
Daemon uses excessive memory systemctl status name Memory field in status
Multiple instances running pgrep -c processname Count > expected
Daemon cannot bind to port `journalctl -u name grep bind`
Tip

systemctl mask servicename is stronger than systemctl disable. Disabled means "don't start at boot" but another service can still start it. Masked creates a symlink to /dev/null, making it impossible to start by any means until unmasked. Use masking for services you never want to run — like telnet or ftp daemons that should not exist on production servers.

Remember

A daemon has no terminal. Its stdout and stderr go nowhere by default unless configured. With systemd, they are captured by journald automatically. With traditional daemons, they redirect to log files or /dev/null. If a daemon is silent when it should be logging, check where its output is going — it may be writing to a file you have not checked.

Frequently Asked Questions

What technically distinguishes a daemon from a regular background process?

A true daemon detaches fully from any controlling terminal — it forks, calls setsid() to start a new session, redirects stdin/stdout/stderr away from the terminal, and typically re-parents to init/systemd (PID 1) after its original parent exits. This means it survives the terminal session that launched it and won't receive terminal signals like SIGHUP when a shell closes, unlike a process simply backgrounded with `&`, which is still tied to that shell session unless explicitly disowned.

What's a common mistake when managing daemons on modern Linux systems?

Writing a custom double-fork daemonization script instead of using systemd's own service management, which already handles process supervision, automatic restarts, logging via journald, and dependency ordering. Modern systemd units can run a program in the foreground (Type=simple) and let systemd manage the daemon behavior itself — hand-rolled daemonization code is largely legacy practice now and tends to handle edge cases (zombie reaping, signal forwarding) worse than systemd does natively.