& 启动的后台任务未脱离终端,退出时会因SIGHUP终止;需用nohup+&、disown或systemd实现真正守护。

用 & 启动后台任务,但进程一关终端就没了
直接在命令末尾加 & 确实能立刻把程序扔到后台,比如 python3 server.py &。但它只是让 shell 不再阻塞,**并不脱离当前终端会话**。一旦你退出 SSH 或关闭终端,shell 会向所有子进程发送 SIGHUP,绝大多数程序(包括 Python、Node.js、bash 脚本)默认收到后就退出。
常见错误现象:jobs 能看到进程,ps 也能查到,但一登出就消失;或者用 nohup 忘了加 &,结果卡住不动。
-
&只是“不等它结束”,不是“不管它死活” - 真正需要的是“脱离终端控制”,得靠
nohup、disown或systemd - 如果程序本身有守护模式(如
nginx -d、redis-server --daemonize yes),优先用它,更干净
nohup + & 是最简单可靠的组合
nohup 的作用是忽略 SIGHUP,配合 & 才算完整:前者保命,后者放行。默认还会把 stdout/stderr 重定向到 nohup.out,避免日志丢失。
使用场景:临时起个服务、跑个耗时脚本、测试环境快速验证。
- 基础写法:
nohup python3 app.py > app.log 2>&1 &—— 显式指定日志文件更可控 - 别只写
nohup cmd &就完事,否则输出全堆在nohup.out,容易混乱 -
2>&1必须写在>后面,顺序错了会重定向失败(比如> app.log 2>&1对,2>&1 > app.log错) - 启动后用
echo $!能拿到刚启动的进程 PID,方便后续管理
想彻底甩手?用 disown 补刀
如果你已经用 & 启了进程,但忘了加 nohup,不用重启——先用 jobs 查编号(比如 [1]+ Running ./script.sh &),再执行 disown %1。它会让 shell “忘记”这个作业,退出时就不会发 SIGHUP。
注意:disown 只对当前 shell 启动的作业有效,且不能恢复到前台(fg 失效)。
- 必须在进程还处于“作业”状态时操作,已退出或被
kill就无效 - 不能跨 shell 使用,比如你在 tmux 里
disown,切到另一个终端就没用了 - 如果进程已挂起(
Stopped),先bg %1再disown
长期运行别硬扛,该上 systemd 就上
开发机临时跑跑可以靠 nohup,但生产环境或需要开机自启、崩溃自动拉起、日志轮转的场景,systemd 是唯一靠谱选择。它不是“高级替代方案”,而是职责所在。
性能/兼容性影响:几乎无额外开销,所有现代 Linux 发行版默认支持;比自己写守护脚本稳定得多。
- 写个
/etc/systemd/system/myapp.service,核心就三行:Type=simple、ExecStart=/usr/bin/python3 /opt/app.py、Restart=on-failure - 别漏掉
User=和WorkingDirectory=,否则权限或路径错得莫名其妙 -
systemctl daemon-reload && systemctl start myapp启动后,日志直接用journalctl -u myapp查,不用管文件路径
真正麻烦的从来不是怎么让它“跑起来”,而是怎么让它“不意外停”。& 是开关,nohup 是保险丝,systemd 是配电箱——用错层级,早晚跳闸。









