日常的后端开发、运维或者服务器管理中,我们经常会看到这样的命令:
nohup npm run start:test > output.log 2>&1 &
很多人知道它能“让进程在后台运行,不会因为关闭终端而中断”,但nohup的原理到底是什么?为什么加个nohup就能让程序一直跑?
本篇:就彻底拆解一下:nohup的底层机制、与其他后台工具的区别,以及如何在实战中正确使用。
🔍 nohup 是什么?
简单理解:
nohup是一个 Linux/Unix 系统自带的命令,作用是:
忽略终端挂断信号(SIGHUP) ,从而让进程在你关闭终端或者SSH断开后继续运行。 no hang up —— 不挂起、不终止。
Linux 中,如果你关闭终端,系统会给当前终端关联的所有进程发送一个挂起信号(SIGHUP),默认行为是直接终止这些进程。
而 nohup 会捕获并忽略这个信号,让你的进程不再受终端控制。
⚙️ nohup 的工作原理
操作系统通过信号(signal)来控制进程。 SIGHUP(信号编号1)是一个“终端挂断信号”,当你关闭SSH或退出终端时,系统会向所有该终端下的前台和后台进程发送这个信号。
默认行为是终止进程。
nohup 做了两件事:
1️⃣ 忽略 SIGHUP 信号
内部执行:
signal(SIGHUP, SIG_IGN);
→ 意思是:遇到SIGHUP,不要退出。
2️⃣ 重定向输入输出
- 如果用户没有指定重定向:
| 文件描述符 | 默认行为 |
|---|---|
| stdin | /dev/null |
| stdout | nohup.out |
| stderr | nohup.out |
避免因为终端关闭,导致输入输出设备消失,从而报错。
是否后台运行? ❌ nohup本身并不负责后台运行。 ✔️ 你需要额外加 &,把它放到后台。
例如:
nohup node app.js &
🧠 nohup 与其他后台工具的区别
| 工具 | 脱离终端 | 后台运行 | 功能特点 |
|---|---|---|---|
nohup | ✔️ | ✔️ (配&) | 忽略SIGHUP,简单可靠 |
& | ❌ | ✔️ | 后台运行,但终端关闭会退出 |
disown | ✔️ | ✔️ | 移除job和终端的关联 |
setsid | ✔️ | ✔️ | 创建新会话,完全脱离终端 |
screen | ✔️ | ✔️ | 虚拟终端,支持断开重连 |
tmux | ✔️ | ✔️ | 更现代的screen,支持多窗口 |
pm2 | ✔️ | ✔️ | 生产级进程管理,支持守护 |
实战示例
nohup 最常用写法
nohup npm run start:test > output.log 2>&1 &
含义:
nohup:忽略SIGHUPnpm run start:test:要执行的命令> output.log:标准输出到日志2>&1:错误输出也一起写到日志&:后台运行
查看日志:
tail -f output.log
更优雅组合:避免nohup.out乱生成,可以这样:
nohup npm run start:test > ./logs/run.log 2>&1 &
或者搭配 disown:
nohup npm run start:test > output.log 2>&1 &
disown
⚠️ nohup 的局限
- 无法监控进程状态。
- 程序崩溃不会自动重启。
- 日志需要手动管理(无限增长)。
👉 所以它适合一次性任务、临时性后台运行,不推荐生产环境长期使用。
🚩 更高级的替代方案
🔥 使用 pm2:
npm install -g pm2
pm2 start npm --name "test-app" -- run start:test
查看状态:
pm2 list
设置开机自启:
pm2 startup
pm2 save
日志查看:
pm2 logs test-app
🔥 使用 tmux 或 screen:
tmux new -s test-app
npm run start:test
分离:
Ctrl + B 然后 D
重连:
tmux attach -t test-app
🎯 总结一句话
nohup = 忽略SIGHUP + 自动重定向IO + 配合 & 后台运行
它是Linux下最简单的“临时后台持久化”工具。
适用场景:
- ✔️ 临时任务
- ✔️ 测试脚本
- ✔️ 短期内不需要崩溃守护的应用
不适用场景:
- ❌ 生产环境长期服务 → 建议用
pm2、systemd或容器(Docker)。
OK,以上便是本次分享~
欢迎加我:atar24,进技术群、交盆友,我会第一时间通过。