
本文详解如何通过 systemd 服务与定时器机制,让需用户交互的 python 脚本在 gcp vm 上长期稳定运行,并规避 ssh 断连、终端退出或系统休眠导致的进程终止问题。
本文详解如何通过 systemd 服务与定时器机制,让需用户交互的 python 脚本在 gcp vm 上长期稳定运行,并规避 ssh 断连、终端退出或系统休眠导致的进程终止问题。
在 Google Cloud Platform(GCP)虚拟机上直接执行 python3 script.py 启动脚本,看似简单,但存在严重运维隐患:一旦 SSH 连接中断、终端关闭、用户登出或系统重启,Python 进程将被 SIGHUP 信号终止——这正是您观察到“运行几小时后脚本自动退出”的根本原因。尤其当脚本依赖标准输入(input() 或 sys.stdin)进行交互时,传统后台化方式(如 &、nohup 或 screen)难以可靠维持 I/O 管道,且缺乏进程健康监控与自动恢复能力。
推荐方案:采用 systemd 用户级服务(User Service)+ 伪 TTY 模拟
systemd 是 linux 系统默认的服务管理器,其用户实例(–user)无需 root 权限即可配置,完美适配 GCP VM 的普通用户环境。关键在于:我们不追求“实时交互”,而是构建一个可持久化、可重启、可日志追踪的守护进程,并为交互逻辑提供安全的输入通道。
✅ 步骤一:改造脚本以支持非阻塞输入(推荐)
避免脚本因 input() 长期阻塞而无法响应 systemd 生命周期管理。建议改用轮询文件或命名管道(FIFO)接收指令:
立即学习“Python免费学习笔记(深入)”;
# persistent_script.py import time import sys import os # 使用 FIFO 接收命令(需提前创建) FIFO_PATH = "/home/$USER/script_input.fifo" def main(): # 创建 FIFO(仅首次) if not os.path.exists(FIFO_PATH): os.mkfifo(FIFO_PATH) print("[INFO] Script started. Waiting for commands via FIFO...") while True: try: with open(FIFO_PATH, 'r') as fifo: line = fifo.readline().strip() if line: print(f"[RECEIVED] {line}") # 在此处处理业务逻辑 result = f"Processed: {line}" print(f"[OUTPUT] {result}") except (OSError, IOError) as e: if e.errno != 6: # Ignore "No such device or address" on FIFO close print(f"[ERROR] FIFO read failed: {e}") time.sleep(1) # 防止忙等待 if __name__ == "__main__": main()
? 提示:使用 echo “hello” > /home/your-user/script_input.fifo 即可向脚本发送指令,输出将打印到 journal 日志中。
✅ 步骤二:创建 systemd 用户服务单元
在用户家目录下创建服务定义(无需 sudo):
mkdir -p ~/.config/systemd/user nano ~/.config/systemd/user/persistent-script.service
内容如下:
[Unit] Description=Persistent Python Script with Input Support After=network.target [Service] Type=simple User=$USER WorkingDirectory=/home/$USER ExecStart=/usr/bin/python3 /home/$USER/persistent_script.py Restart=always RestartSec=5 StandardOutput=journal StandardError=journal SyslogIdentifier=py-persistent # 关键:启用用户级环境变量和会话上下文 Environment="XDG_RUNTIME_DIR=/run/user/%U" Environment="HOME=/home/%U" [Install] WantedBy=default.target
启用并启动服务:
# 重载用户 unit 配置 systemctl --user daemon-reload # 启用开机自启(登录即生效) systemctl --user enable persistent-script.service # 立即启动 systemctl --user start persistent-script.service # 查看状态与实时日志 systemctl --user status persistent-script.service journalctl --user -u persistent-script.service -f
⚠️ 注意事项与最佳实践
- 不要使用 Type=forking 或 Type=notify:交互式脚本通常无标准守护进程协议,simple 类型最稳妥;
- 禁用 KillMode=control-group 默认行为:若需更精细控制,可在 [Service] 中添加 KillMode=mixed 防止子进程误杀;
- 避免 root 依赖:GCP VM 默认以普通用户登录,–user 模式完全满足权限需求,无需提权;
- 日志是调试核心:所有 print() 输出均自动进入 journal,用 journalctl –user -u xxx -n 100 快速排查;
- 资源限制(可选):在 [Service] 中添加 MemoryLimit=512M 或 CPUQuota=50% 防止失控;
- 替代方案对比:
- nohup python3 script.py &:无进程管理、无自动重启、日志分散;
- screen/tmux:依赖终端会话,系统重启后丢失;
- PythonAnywhere:免费版资源受限、无法自定义系统服务、无 stdin 控制权。
通过以上配置,您的 Python 脚本将作为受 systemd 全生命周期管理的守护进程持续运行——即使 SSH 断开、用户登出或 VM 重启(配合 enable),它都会自动拉起并保持就绪状态。结合 FIFO 或 REST API(如 flask 轻量接口)接收外部指令,即可在生产环境中安全、可维护地承载交互式任务。