如何在 GCP 虚拟机上持久运行 Python 脚本(支持交互式输入)

1次阅读

如何在 GCP 虚拟机上持久运行 Python 脚本(支持交互式输入)

本文详解如何通过 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 轻量接口)接收外部指令,即可在生产环境中安全、可维护地承载交互式任务。

text=ZqhQzanResources