在Linux系统运维和开发过程中,我们经常需要让某些程序在后台持续运行,即使终端关闭或用户注销也不中断。比如Web服务器、数据库服务、数据采集程序等长期运行的服务,都需要可靠的后台运行机制。直接在前台运行这些程序显然不现实——终端一旦关闭,进程就会随之终止。
传统做法是用&符号将命令放到后台:
bash复制python data_processor.py &
但这种方式存在明显缺陷:当启动该进程的终端会话结束时,进程仍然会收到SIGHUP信号而终止。此外,这种简单后台运行方式缺乏对进程状态的监控和管理能力。
nohup(no hang up)是Linux/Unix系统自带的工具,其核心功能是让进程忽略SIGHUP信号。当终端关闭时,系统会向该终端关联的所有进程发送SIGHUP信号,默认会导致进程终止。nohup通过以下机制实现进程守护:
典型的使用方式:
bash复制nohup python3 app.py > app.log 2>&1 &
这里:
> app.log 将标准输出重定向到app.log2>&1 将标准错误也重定向到标准输出&表示放入后台bash复制nohup ./start_server.sh > /var/log/server.log 2> /var/log/server.err &
bash复制# 在zsh中需要这样使用
nohup command &!
bash复制# 确保环境变量正确加载
nohup bash -c 'source ~/.bashrc && python script.py' &
注意:nohup不会自动将进程变为daemon,它只是让进程忽略挂断信号。真正的服务进程应该实现双fork等daemon化操作。
start-stop-daemon是Linux系统(特别是Debian系)中专门为初始化脚本设计的进程管理工具。相比nohup,它提供了更完善的服务管理能力:
常用参数说明:
| 参数 | 作用 | 示例 |
|---|---|---|
| --start | 启动进程 | --start --background |
| --stop | 停止进程 | --stop --pidfile /var/run/foo.pid |
| --background | 后台运行 | --background --make-pidfile |
| --exec | 指定可执行文件 | --exec /usr/sbin/foo |
| --name | 按进程名匹配 | --name foo |
| --pidfile | 指定PID文件 | --pidfile /var/run/foo.pid |
| --user | 指定运行用户 | --user nobody |
典型的服务管理脚本片段:
bash复制case "$1" in
start)
start-stop-daemon --start --background \
--pidfile /var/run/myservice.pid \
--make-pidfile \
--exec /usr/local/bin/myservice \
--chuid myservice:myservice \
-- \
--config /etc/myservice.conf
;;
stop)
start-stop-daemon --stop \
--pidfile /var/run/myservice.pid \
--retry 10
;;
esac
| 特性 | nohup | start-stop-daemon |
|---|---|---|
| 忽略SIGHUP | ✓ | ✓ |
| 后台运行 | ✓ | ✓ |
| 进程状态管理 | ✗ | ✓ |
| PID文件支持 | ✗ | ✓ |
| 用户权限控制 | ✗ | ✓ |
| 服务生命周期管理 | ✗ | ✓ |
| 资源限制设置 | ✗ | ✓ |
| 系统集成度 | 低 | 高 |
nohup适合:
start-stop-daemon适合:
bash复制# 使用logrotate管理nohup.out
/var/log/nohup.out {
daily
rotate 7
missingok
notifempty
compress
}
bash复制# 简单的监控重启脚本
while true; do
nohup python worker.py >> worker.log 2>&1
sleep 10
done
bash复制start-stop-daemon --start \
--limit-cpu 300 \
--limit-as 512000 \
--exec /usr/sbin/service
bash复制# 对于worker pool模式的服务
for i in {1..4}; do
start-stop-daemon --start \
--pidfile /var/run/worker_${i}.pid \
--exec /usr/bin/worker \
-- \
--id ${i}
done
问题:nohup进程意外终止
问题:环境变量丢失
bash复制# 解决方案
nohup env DISPLAY=:0 python gui_app.py &
错误:"start-stop-daemon: unable to open pidfile"
--make-pidfile参数自动创建错误:"process already running"
--name参数是否过于宽泛对于更复杂的服务管理需求,现代Linux系统还提供了其他选择:
systemd服务单元:提供最完善的服务管理能力
ini复制[Unit]
Description=My Service
[Service]
ExecStart=/usr/bin/my-service
Restart=always
User=myuser
[Install]
WantedBy=multi-user.target
supervisor:适合管理多个进程
ini复制[program:worker]
command=python worker.py
directory=/opt/worker
user=worker
autostart=true
autorestart=true
screen/tmux:交互式会话管理
bash复制tmux new -d -s mysession 'python service.py'
选择哪种工具取决于具体需求:简单临时任务用nohup,系统服务用start-stop-daemon或systemd,复杂应用集群可以考虑supervisor等专业工具。