nohup 是什么
nohup 让命令忽略 SIGHUP 信号。终端关闭时,内核会向该终端上的进程发 SIGHUP,交互式 shell 默认把收到的挂断转成对作业的 HUP,进程因此退出;nohup 把这个信号设为忽略,进程就能活过终端会话。它同时处理标准流:标准输入指向 /dev/null(避免后台进程阻塞在读终端),标准输出与标准错误在未重定向时追加进当前目录的 nohup.out。所以 nohup 的定位是「让一次性长任务脱离终端」,它不负责崩溃自动拉起,也不负责开机自启。
基本信息
| 适用平台 | Linux/macOS(GNU coreutils 与 BSD 各自的 nohup,行为一致) |
|---|---|
| 命令语法 | nohup 命令 [参数] > 日志 2>&1 & |
| 行为要点 | 忽略 SIGHUP;stdin 指向 /dev/null;输出未重定向时写入当前目录 nohup.out |
| 配套手段 | & 后台运行、disown 移除作业表、setsid 新建会话、systemd 做真正守护 |
| 权限说明 | 任何用户可用;日志与 nohup.out 所在目录需有写权限 |
典型使用场景
- 长耗时任务:数据迁移、大目录备份,跑几十分钟到几小时,不能因断线中断
- 临时服务:内部工具或调试进程,不值得为它写 systemd 单元
- 远程执行:ssh 登录后启动任务并记下 PID,随后断开连接不影响任务
- 资源让步:nohup nice -n 10 ./batch.sh 让批处理不与在线业务抢 CPU
- 一次性脚本:升级前的导出、日志归档等不常驻的运维动作
常用示例
常用示例
nohup ./backup.sh > /var/log/backup.log 2>&1 & # 标准写法
echo $! > /run/backup.pid # 记下 PID 便于后续管理
nohup python3 worker.py </dev/null > worker.log 2>&1 &
nohup nice -n 10 ./batch.sh > batch.log 2>&1 & # 降优先级
setsid ./long-task.sh > task.log 2>&1 < /dev/null & # 脱离会话,比 nohup 更彻底
ps -o pid,ppid,sid,stat,cmd -p $(cat /run/backup.pid) # 核对进程状态几种脱离终端的方式
| 方式 | 解决什么 | 不解决什么 |
|---|---|---|
| nohup | 忽略 SIGHUP,终端断开后继续运行 | 不自启、不自动重启、不管日志轮转 |
| setsid | 新建会话,与终端和原进程组彻底解耦 | 同样没有重启与开机自启能力 |
| systemd 单元 | 开机自启、崩溃拉起、日志归集、资源限制 | 需要写单元文件,改动要走 daemon-reload |
| screen/tmux | 保活会话并保留可交互的终端 | 依赖会话管理,不适合无人值守的长期服务 |
已经跑在后台的任务可以用 disown -h %1 补上 HUP 免疫,但已经收到过 SIGHUP 的进程救不回来,顺序要在断线前完成。
nohup 只免疫 SIGHUP 一种信号:进程自身崩溃、OOM 被杀都不会自动恢复。要求「挂了自动重启」的服务请用 systemd 的 Restart= 策略,而不是靠 nohup。