1. 为什么需要nohup运行Python脚本?
每次SSH连接断开后,正在运行的Python脚本就会突然终止,这种经历估计不少开发者都遇到过。上周我就因为服务器连接超时,导致一个跑了3天的数据分析脚本前功尽弃。这时候就需要nohup这个"守护神"出场了——它能让你在关闭终端后,程序依然坚挺地运行。
nohup的工作原理其实很有意思。当终端关闭时,系统会向所有关联进程发送SIGHUP信号(Signal Hang UP),而nohup的作用就是让程序免疫这个信号。想象一下你的Python脚本是个正在做实验的科学家,nohup就是给实验室装了不间断电源,即使大楼断电,实验也能继续进行。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础用法与日志管理
2.1 最简启动命令
先来看最基本的用法:
bash复制nohup python your_script.py &
这个命令做了三件事:
- 用nohup包裹Python解释器
- 执行你的脚本文件
- 末尾的&符号让进程在后台运行
但这样有个问题——所有输出都会默认写入nohup.out文件,时间久了可能撑爆磁盘。我就曾因此收到过服务器的磁盘告警。
2.2 高级日志控制方案
更专业的做法是指定日志路径:
bash复制nohup python your_script.py > custom.log 2>&1 &
这里有几个关键点:
>重定向标准输出到custom.log2>&1将标准错误也合并到同一文件- 最后的&保持后台运行
建议按日期分割日志,可以这样改进:
bash复制LOG_FILE="script_$(date +%Y-%m-%d).log"
nohup python your_script.py > ${LOG_FILE} 2>&1 &
3. 实战中的进阶技巧
3.1 保持环境一致性
遇到过脚本在终端能运行,用nohup就报错的情况吗?这通常是环境变量的问题。解决方案是:
bash复制nohup env -i PATH=$PATH python your_script.py > output.log 2>&1 &
env -i清空环境变量,再显式指定PATH,确保与终端环境一致。
3.2 进程监控与管理
启动后如何确认程序在运行?这几个命令很实用:
bash复制# 查看后台Python进程
pgrep -fl python
# 实时查看日志
tail -f output.log
# 按内存排序查看
ps aux --sort=-%mem | grep python
4. 常见问题排雷指南
4.1 脚本突然停止
可能原因:
- 代码中有sys.exit()
- 遇到未捕获的异常
- 服务器资源不足被OOM Killer终止
解决方案:
python复制try:
main()
except Exception as e:
with open('error.log', 'a') as f:
f.write(f"[{datetime.now()}] {str(e)}\n")
4.2 日志文件不更新
检查要点:
- 磁盘空间(df -h)
- 文件权限(ls -l)
- 脚本是否真正在运行(ps aux)
4.3 性能优化建议
长时间运行的脚本要注意:
- 定期flush日志文件
- 使用logging模块替代print
- 增加内存监控逻辑
示例代码:
python复制import psutil
import logging
logging.basicConfig(filename='app.log', level=logging.INFO)
def check_memory():
if psutil.virtual_memory().percent > 90:
logging.warning("Memory usage over 90%!")
5. 企业级方案推荐
对于生产环境,建议使用更专业的进程管理工具:
| 工具 | 优点 | 适用场景 |
|---|---|---|
| systemd | 系统集成度高 | 长期运行的服务 |
| supervisor | 配置简单 | 开发测试环境 |
| docker | 环境隔离 | 微服务架构 |
| screen/tmux | 可交互 | 临时调试任务 |
以systemd为例,创建服务文件:
ini复制# /etc/systemd/system/python_app.service
[Unit]
Description=Python Application
[Service]
User=deploy
WorkingDirectory=/opt/app
ExecStart=/usr/bin/python /opt/app/main.py
Restart=always
[Install]
WantedBy=multi-user.target
启用服务:
bash复制sudo systemctl daemon-reload
sudo systemctl start python_app
sudo systemctl enable python_app
6. 日志分析实战案例
分享一个真实场景:我们有个数据处理脚本突然变慢,通过分析nohup日志发现了问题:
bash复制# 统计错误出现频率
grep "ERROR" application.log | awk '{print $4}' | sort | uniq -c | sort -nr
# 提取慢查询
grep "Processing time" application.log | awk '$NF > 5 {print}'
最终发现是数据库连接没有正确关闭,导致连接池耗尽。修正后性能提升了8倍。
7. 我的踩坑记录
-
缓冲问题:Python的输出有缓冲,可能导致日志不及时。解决方案:
bash复制nohup python -u your_script.py > output.log &-u参数强制无缓冲输出 -
编码问题:日志中出现乱码时,需要明确指定编码:
python复制import sys import codecs sys.stdout = codecs.getwriter('utf8')(sys.stdout) -
信号处理:优雅退出很重要:
python复制import signal def handler(signum, frame): save_progress() sys.exit(0) signal.signal(signal.SIGTERM, handler)
最后分享一个监控脚本是否存活的小技巧:
bash复制crontab -e
# 添加:
*/5 * * * * pgrep -f "your_script.py" || nohup python /path/to/your_script.py > /path/to/log 2>&1 &
