第一次接触nohup是在2013年处理一个生产环境的数据迁移任务时。当时我需要运行一个耗时超过8小时的数据库导出脚本,但担心SSH连接中断导致任务终止。同事轻描淡写地说:"用nohup啊,记得重定向输出"。这个看似简单的命令从此成为我运维工具箱中的常备利器。
nohup(no hang up的缩写)是Linux/Unix系统中的一个基础但至关重要的命令,它解决的核心痛点是:当用户注销(logout)或关闭终端时,系统默认会向该会话关联的所有进程发送SIGHUP信号,导致进程被终止。而nohup的作用就是让进程忽略SIGHUP信号,实现持久化运行。
最基础的nohup使用方式如下:
bash复制nohup command [args] &
这个命令会立即返回一个进程ID,并将command放入后台运行。但这样使用存在明显问题——所有输出默认会写入当前目录的nohup.out文件,长期运行可能导致这个文件体积爆炸。
经过多年实践,我总结出更完善的日志记录方案:
bash复制nohup command [args] >> /path/to/logfile 2>&1 &
这个命令实现了:
重要提示:重定向符号使用">>"而非">",这是为了避免每次运行覆盖原有日志。我在一次重要任务中曾因此丢失关键日志,教训深刻。
直接使用nohup的默认日志记录方式会导致单个日志文件过大。我推荐结合logrotate实现自动轮转:
bash复制mkdir -p /var/log/myapp
chmod 755 /var/log/myapp
code复制/var/log/myapp/nohup.log {
daily
rotate 30
compress
missingok
notifempty
create 644 root root
}
单纯使用nohup并不保证进程持续运行。我常用这个组合方案:
bash复制nohup command >> /var/log/myapp/nohup.log 2>&1 &
echo $! > /var/run/myapp.pid
保存PID文件后,可以方便地编写监控脚本:
bash复制#!/bin/bash
PID=$(cat /var/run/myapp.pid 2>/dev/null)
if ! kill -0 $PID > /dev/null 2>&1; then
echo "Process $PID is not running. Restarting..."
nohup command >> /var/log/myapp/nohup.log 2>&1 &
echo $! > /var/run/myapp.pid
fi
当发现nohup命令执行后没有生成日志文件时,按以下步骤排查:
bash复制strace -f -o trace.log nohup command...
nohup运行的环境可能与交互式shell不同,导致环境变量丢失。解决方案:
bash复制nohup bash -c 'source /path/to/env && command' >> logfile 2>&1 &
某些程序(如Python)的输出可能被缓冲,导致日志不及时更新。解决方法:
bash复制nohup python -u script.py >> logfile 2>&1 &
bash复制nohup stdbuf -oL command >> logfile 2>&1 &
需要连续执行多个命令时,建议使用子shell:
bash复制nohup bash -c 'command1 && command2 || command3' >> logfile 2>&1 &
在日志中添加时间戳便于排查:
bash复制nohup command | while IFS= read -r line; do
echo "$(date '+%Y-%m-%d %H:%M:%S') $line"
done >> logfile 2>&1 &
对于高性能要求的应用,建议:
bash复制nohup command > >(tee -a logfile) 2> >(tee -a logfile >&2) &
虽然nohup简单易用,但在生产环境中还有其他选择:
| 工具 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| nohup | 无需额外安装,简单可靠 | 功能有限,缺乏监控 | 临时任务,快速测试 |
| screen/tmux | 会话可恢复,交互性强 | 需要保持会话 | 开发调试环境 |
| systemd | 完善的进程管理,自动重启 | 配置复杂 | 生产环境服务 |
| supervisor | 集中管理,web界面 | 需要额外安装 | 多进程监控环境 |
在最近的一次金融系统迁移项目中,我们最终选择组合方案:使用nohup运行初始化脚本(因为只需运行一次),而将常驻服务交给systemd管理。这种混合策略既保证了灵活性,又获得了企业级的管理能力。