在 Linux 中,守护进程(Daemon)是指在后台运行、与终端无关、生命周期长的进程。下面我从概念 → 手写步骤 → 示例代码 → 常见做法四个方面讲清楚。
/var/run/xxx.pid 保存 PIDfork() 创建子进程setsid() 创建新会话fork()(可选,防止重新获得终端)/umask(0)syslog 写日志#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
void daemonize() {
pid_t pid;
// 1. fork
pid = fork();
if (pid < 0) exit(1);
if (pid > 0) exit(0); // 父进程退出
// 2. 创建新会话
if (setsid() < 0) exit(1);
// 3. 再 fork(防止重新打开终端)
pid = fork();
if (pid < 0) exit(1);
if (pid > 0) exit(0);
// 4. 改变工作目录
chdir("/");
// 5. 重设文件掩码
umask(0);
// 6. 关闭标准 IO
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
// 7. 使用 syslog
openlog("mydaemon", LOG_PID, LOG_DAEMON);
}
int main() {
daemonize();
while (1) {
syslog(LOG_INFO, "daemon is running...");
sleep(10);
}
return 0;
}
编译运行:
gcc daemon.c -o mydaemon
./mydaemon
ps -ef | grep mydaemon
daemon() 函数(简化版)#include <unistd.h>
daemon(0, 0);
不推荐用于生产,但适合简单程序
不需要自己写守护逻辑
/etc/systemd/system/mydaemon.service[Unit]
Description=My Daemon
[Service]
ExecStart=/usr/local/bin/mydaemon
Restart=always
[Install]
WantedBy=multi-user.target
启用:
systemctl daemon-reload
systemctl start mydaemon
systemctl enable mydaemon
✅ 优点:
import os, sys, time
pid = os.fork()
if pid > 0:
sys.exit()
os.setsid()
os.chdir("/")
os.umask(0)
while True:
with open("/tmp/daemon.log", "a") as f:
f.write("running\n")
time.sleep(10)
实际项目建议用
python-daemon库
| 场景 | 推荐方式 |
|---|---|
| 学习原理 | 手写 fork + setsid |
| 简单工具 | daemon() |
| 生产环境 | systemd |
| 脚本语言 | systemd + 普通程序 |
如果你愿意,我可以:
你现在的用途是什么?(服务?监控?采集?)