怎么让Python脚本在服务器后台持续运行

林舟
林舟
发布时间:2026-10-21 | 2人浏览过
原创

通过 SSH 远程连接 Linux 服务器运行 Python 脚本时,默认情况下一旦关闭终端或网络波动中断,脚本就会随之退出。要让 Python 程序在后台脱离终端、稳定持续运行,核心路径有三种:使用 nohup 与输出重定向实现轻量快速运行、使用 tmux 等终端复用工具保持交互式会话,以及通过 systemd 配置系统级守护服务以支持开机自启和故障重启。本文将由浅入深讲解具体操作、底层机制与选型依据。

一、为什么终端断开会导致 Python 脚本退出

在 Linux 操作系统中,通过 SSH 登录服务器后,系统会为当前连接创建一个伪终端(PTY)以及一个关联的 Bash 会话。当我们在命令行直接执行 python3 app.py 时,该 Python 进程作为当前终端会话的前台子进程运行。

当网络中断或直接关闭 SSH 客户端窗口时,系统内核会检测到控制终端的断开,并向该会话的首进程发送一个挂断信号——SIGHUP(Signal Hang Up)。默认情况下,会话内的子进程接收到该信号后都会被强制终止。因此,要让脚本在关闭连接后仍能继续工作,关键在于阻断 SIGHUP 信号向进程传递,或者将脚本从当前终端会话中彻底剥离解绑。

怎么让Python脚本在服务器后台持续运行
图 1:SSH 终端生命周期与 SIGHUP 信号处理机制对比

二、方案一:使用 nohup 与重定向(最轻量的快速解法)

nohup(no hang up)是 Linux 系统自带的工具,专门用于忽略 SIGHUP 信号。配合末尾的 & 符号,可以让程序直接在后台启动并脱离控制终端。

1. 推荐的完整运行命令

nohup python3 -u app.py > app.log 2>&1 &

这个由多个参数组成的命令是业界经过大量实践得出的标准写法,各部分的具体作用如下:

  • nohup:告知操作系统忽略所有的挂断(SIGHUP)信号,防止会话关闭时进程被误杀。
  • python3 -u:非常关键的参数。Python 在输出重定向到文件时默认会开启缓冲区,若不加 -u,控制台输出的日志可能很久都不会写入磁盘文件;-u 强制取消标准输出与标准错误的缓冲,实现实时写盘。
  • > app.log:将脚本的标准输出(stdout,文件描述符 1)重定向写入到 app.log 文件中。
  • 2>&1:将标准错误(stderr,文件描述符 2)重定向合并到标准输出(&1)中,确保报错堆栈也能完整记录在日志内。
  • &:放在命令最后,表示将该命令转入后台执行,立即释放当前终端提示符,不阻塞用户操作。
怎么让Python脚本在服务器后台持续运行
图 2:nohup 命令语法解构与 I/O 重定向流转图

2. 日志查看与进程维护

执行后台启动后,终端通常会输出一个代表该进程的数字编号(PID)。后续可通过以下命令进行日常维护:

  • 查看实时运行日志:
    tail -f app.log
    使用 tail -f 可以像前台执行一样动态刷新输出,按 Ctrl + C 即可退出日志查看,该退出动作不会影响后台正在运行的 Python 进程。
  • 确认进程是否在运行:
    ps -ef | grep app.py
    在输出结果中可以观察到该进程的 PID、父进程 PID(通常会变成 1 号 init/systemd 进程)、CPU/内存占用及运行时间。
  • 正常停止后台进程:
    kill <PID>
    向指定进程发送 SIGTERM 信号,通知程序平稳退出;若脚本无响应卡死,可使用强制终止命令 kill -9 <PID>。

三、方案二:使用 tmux 或 screen 终端复用(交互与排错利器)

nohup 适合不需要任何手动输入的纯后台服务。但如果程序在运行过程中需要观察彩色终端控制台、需要临时通过键盘输入参数,或者你希望随时重新连接进当前执行界面,终端复用工具(Terminal Multiplexer)是最好的选择。最主流的工具是 tmux。

1. tmux 的标准工作流

  1. 安装 tmux(若服务器未预装):
    sudo apt install tmux      # Ubuntu / Debian
    sudo yum install tmux      # CentOS / RHEL
  2. 创建一个独立的命名会话:
    tmux new -s my_task
    此时会进入一个全新的终端窗口,底部会出现绿色的 tmux 状态栏。
  3. 在 tmux 会话内正常启动 Python 脚本:
    python3 app.py
    脚本就像平时在本地电脑一样正常输出打印。
  4. 脱离(Detach)会话返回母机终端: 依次按下键盘组合键:Ctrl + B,松开后再按下字母 D。此时终端会提示 [detached (from session my_task)],返回到最初的 SSH 命令行中,而 my_task 内部的脚本依然在服务器后台全力运行。此时你可以放心地直接关闭 SSH 客户端。
  5. 重新接入(Attach)已有会话: 重新通过 SSH 登录服务器后,执行:
    tmux attach -t my_task
    终端会立即恢复到脚本运行的现场,所有输出与上下文完全保留。
  6. 结束会话: 在 tmux 窗口内当脚本执行完毕后,直接输入 exit 即可销毁该会话;或者在外层终端执行 tmux kill-session -t my_task。

四、方案三:配置 systemd 服务(生产环境标准解法)

无论是 nohup 还是 tmux,在面临服务器断电重启、系统补丁重启或 Python 程序出现未捕获异常崩溃时,都无法实现自动恢复。生产环境(如企业爬虫、Web 后台、自动化数据同步任务)通常统一采用现代 Linux 系统的服务管理器——systemd。

1. 编写服务单元配置文件

假设我们的 Python 脚本位于 /home/ubuntu/app/main.py,其运行环境使用的是同目录下的虚拟环境 /home/ubuntu/app/venv。我们使用 root 权限在 /etc/systemd/system/ 目录下创建一个名为 py_worker.service 的服务文件:

sudo nano /etc/systemd/system/py_worker.service

在文件中填入如下标准配置内容:

[Unit]
Description=My Python Persistent Worker Service
After=network.target

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/app
ExecStart=/home/ubuntu/app/venv/bin/python3 -u /home/ubuntu/app/main.py
Restart=always
RestartSec=5
Environment=PYTHONUNBUFFERED=1

# 日志输出配置(可选输出到文件或交由 systemd journal 管理)
StandardOutput=append:/home/ubuntu/app/worker.log
StandardError=append:/home/ubuntu/app/worker_error.log

[Install]
WantedBy=multi-user.target

核心配置项含义说明:

  • User:指定运行该脚本的系统用户,避免直接使用 root 运行非特权脚本,提高安全性。
  • WorkingDirectory:脚本的工作目录。设置该项后,代码中读写相对路径文件就不会发生 FileNotFoundError。
  • ExecStart:必须使用绝对路径指定 Python 解释器和脚本入口文件。如果有虚拟环境,直接填写虚拟环境内的 bin/python3 绝对路径。
  • Restart=always:进程无论是因为异常抛出崩溃还是被系统误杀,systemd 都会自动重新拉起。
  • RestartSec=5:崩溃后等待 5 秒再执行重启,防止代码逻辑错误导致无限密集重启打满 CPU。
怎么让Python脚本在服务器后台持续运行
图 3:systemd 服务从配置编写到运维管理的完整生命周期步骤

2. 日常运维管理命令汇总

# 启动 / 停止 / 重启服务
sudo systemctl start py_worker
sudo systemctl stop py_worker
sudo systemctl restart py_worker

# 查看服务状态
sudo systemctl status py_worker

# 开启 / 关闭开机自启
sudo systemctl enable py_worker
sudo systemctl disable py_worker

五、三种后台运行方案的选型对比与决策

在面对不同任务类型时,盲目选择最复杂的方案反而会增加操作负担,而过于简单的方案又可能在生产中发生故障。我们可以通过下表与决策树来快速选择最适合的工具:

对比维度 nohup 命令 tmux / screen 会话 systemd 服务
适用场景 临时脚本、一次性数据清洗、离线抓取 长时间训练模型、排查问题、需控制台交互 生产 API、长期常驻服务、消息队列消费
配置成本 极低(单行命令直接启动) 低(学习几个快捷键即可熟练使用) 中(需编写 service 文件并具备 sudo 权限)
控制台恢复 不支持(只能通过 tail 查看重定向文件) 完美支持(随时 attach 恢复实时交互界面) 不支持交互(通过 journalctl 或日志文件查阅)
开机自启动 不支持 不支持 原生支持(enable 即自动注册)
崩溃自动拉起 不支持(进程异常退出后即终止) 不支持 原生支持(Restart=always 参数)
怎么让Python脚本在服务器后台持续运行
图 4:Python 后台运行需求决策树与适用场景划分

六、后台运行常见问题与排查指南

1. 日志文件为什么长时间为空(输出缓冲问题)

很多开发者在执行 nohup python3 script.py > run.log & 后,使用 tail -f run.log 发现日志空空如也,误以为脚本没有执行。这是因为 Python 侦测到标准输出不是交互式 TTY 终端而是重定向文件时,会自动切换为块缓冲模式(Block Buffering),通常要等到累积满 4KB 或 8KB 数据才会统一刷入磁盘。

解决办法:在执行命令时加入 -u 开关,例如 python3 -u script.py;或者在环境变量中设置 export PYTHONUNBUFFERED=1;如果是在 Python 代码内部,可以在 print() 函数中加入参数 print("...", flush=True)。

2. 相对路径导致的 FileNotFoundError

当使用 nohup 或 systemd 运行时,脚本的当前执行目录(CWD)取决于你执行命令时的终端位置或 service 中的 WorkingDirectory 配置。如果在代码中直接使用 open("data/config.json"),极易因相对路径基准变化而引发报错崩溃。

解决办法:在 Python 代码中采用基于当前脚本所在目录的绝对路径定位:

from pathlib import Path

# 获取当前脚本所在目录的绝对路径
BASE_DIR = Path(__file__).resolve().parent
config_path = BASE_DIR / "data" / "config.json"

3. 如何确认后台脚本的真实资源占用

长期运行在服务器后台的 Python 脚本如果存在内存泄漏或死循环,可能导致服务器崩溃。可通过以下 Linux 命令快速检查:

# 查看该 Python 进程的 CPU 与内存实时占用
top -p $(pgrep -f app.py)

# 或使用 ps 查看简报
ps -o pid,user,%cpu,%mem,stat,start,time,command -p $(pgrep -f app.py)

如果发现状态显示为 Z(Zombie 僵尸进程)或 D(不可中断的休眠,通常在等待死锁磁盘 I/O),需检查代码中的多线程、网络套接字及资源释放逻辑。

总结:临时运行和排查优先选 tmux 或 nohup -u;一旦程序需要长期对业务负责、要求无人值守与自愈能力,务必投入少量时间配置 systemd 服务,这是保障服务器应用健壮运行最规范的做法。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表