根本原因是Python脚本读取断开的stdin导致退出;需显式重定向/dev/null、规范日志路径、加异常兜底、用唯一标识管理进程。

nohup 启动 Python 脚本后为什么一关终端就退出?
根本原因不是 nohup 失效,而是没处理好标准输入(stdin)。很多 Python 脚本在启动时会尝试读取 sys.stdin(比如用了 input()、getpass.getpass(),或某些库默认检测交互终端),一旦 stdin 断开,就直接抛 EOFError 或 IOError 退出。
实操建议:
- 加
< /dev/null显式断开 stdin:nohup python script.py < /dev/null > out.log 2>&1 & - 检查脚本是否隐含依赖交互——删掉调试用的
input(),或用sys.stdin.isatty()做防护 - 用
ps aux | grep script.py确认进程是否真在运行,别只看终端没报错就以为成功
日志重定向写法不对,结果全丢进 nohup.out 里了
nohup 默认把 stdout 和 stderr 合并写入当前目录的 nohup.out,但这个路径不固定、权限可能受限、还容易和别的脚本混在一起。想精准控制日志,必须显式重定向。
常见错误现象:执行了 nohup python a.py &,却在当前目录找不到 nohup.out(被写到家目录去了),或者日志内容空——其实是 stderr 没捕获,错误被吞了。
立即学习“Python免费学习笔记(深入)”;
实操建议:
- 强制指定日志路径:
nohup python script.py > /var/log/myscript.log 2>&1 & - 用
2>&1把 stderr 合并进 stdout,避免错误信息丢失;单独重定向 stderr(如2> err.log)也行,但得同时管两个文件 - 确保目标目录可写:
mkdir -p /var/log/myapp && chown myuser:myuser /var/log/myapp
Python 脚本自己 exit() 或异常退出,nohup 也救不了
nohup 只防止 SIGHUP 信号中断进程,对脚本内部逻辑崩溃完全无感。常见场景:未捕获的异常、数据库连接失败、文件路径不存在、环境变量缺失。
性能与兼容性影响:这类退出往往发生得很快,你甚至来不及查日志——因为日志可能还没 flush 就结束了。
实操建议:
- 加最外层异常兜底:在脚本入口包一层
try...except Exception as e:,把 traceback 写进日志再sys.exit(1) - 手动 flush 日志:如果用
print(..., file=sys.stderr)记录,加上flush=True参数 - 别信“后台运行=稳如老狗”,先本地跑一次
python script.py < /dev/null模拟后台环境,看会不会崩
想随时重启/查状态,但 ps grep 太难找
光靠 ps aux | grep python 容易漏匹配(比如多个脚本都叫 main.py),也难区分是哪个用户、哪个虚拟环境启的。更麻烦的是,重启时 kill 错进程,或残留僵尸进程。
实操建议:
- 启动时加唯一标识:
nohup python script.py --name myservice < /dev/null > log.txt 2>&1 &,然后用ps aux | grep myservice - 用
pgrep -f "myservice"更可靠;杀进程用pkill -f "myservice",比kill $(pidof python)安全 - 记录 pid 到文件:
nohup python script.py < /dev/null > log.txt 2>&1 & echo $! > /tmp/myservice.pid,后续操作有据可依
真正麻烦的从来不是怎么让它跑起来,而是它半夜挂了你不知道,或者日志里全是乱码时间戳,又或者不同环境里 nohup 行为不一致——这些细节不提前压住,后面排查成本翻倍。










