Forking Daemon Service
Configure a systemd unit file for a traditional forking daemon. Understand PIDFile tracking, how systemd monitors forked processes, and when to use the forking service type.
Detailed Explanation
Managing Traditional Daemons with systemd
Traditional Unix daemons fork a child process and exit the parent. The Type=forking service type tells systemd to expect this behavior. Systemd considers the service started when the parent process exits successfully.
[Unit]
Description=Legacy Application Daemon
After=network.target
[Service]
Type=forking
PIDFile=/var/run/myapp.pid
ExecStart=/usr/sbin/myapp --daemon
ExecStop=/bin/kill -s TERM $MAINPID
Restart=on-failure
RestartSec=10
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
[Install]
WantedBy=multi-user.target
Understanding the Forking Process
When Type=forking is set, the startup sequence works like this:
- Systemd executes ExecStart (
/usr/sbin/myapp --daemon) - The application forks a child process
- The parent process exits with code 0
- Systemd reads the PID of the child from
PIDFile - Systemd now monitors the child process
PIDFile is Critical
For forking services, PIDFile= is essential. Without it, systemd may lose track of which process is the main service process. The application must write its child's PID to this file during the forking process.
PIDFile=/var/run/myapp.pid
If the PIDFile doesn't match the actual daemon PID, systemd will fail to monitor the service correctly, potentially leading to zombie processes or incorrect status reporting.
Common Issues with Forking Services
- Missing PIDFile: Service appears as "activating" forever because systemd can't confirm the fork succeeded.
- Double-forking: Some daemons fork twice. Systemd handles this if the final PID is written correctly.
- PID reuse: If the PIDFile contains a stale PID, systemd may monitor the wrong process.
When to Avoid Forking
Most modern applications support running in the foreground. Prefer Type=simple whenever possible because:
- No PIDFile management complexity
- Simpler process tracking
- Faster startup detection
- Better compatibility with cgroups and resource controls
Use Case
Running a legacy C/C++ daemon that was designed to daemonize itself via fork(), such as older versions of Apache httpd, MySQL, or custom in-house daemons that don't support foreground mode.