如何让Python脚本在Screen会话中自动重启自身?
实现Python脚本自动检测并切换到Screen会话运行
核心思路
Screen会话会自动设置STY环境变量,我们可以通过检测这个变量判断脚本是否在Screen中运行;如果不在,就用os.execvp替换当前进程,启动Screen会话并在其中重新运行脚本。
完整实现代码
import os import sys def is_in_screen(): # 检测STY环境变量,存在则说明处于Screen会话 return 'STY' in os.environ def restart_in_screen(): # 获取当前Python解释器路径,避免硬编码导致环境不一致 python_exec = sys.executable # 构造Screen命令参数: # -D -m:强制启动分离式会话,断开连接后脚本仍能后台运行 # -S:指定会话名称,方便后续用screen -r 重新连接 screen_cmd = [ 'screen', '-D', '-m', '-S', 'long_running_script', python_exec ] + sys.argv # 传递原脚本的所有启动参数 # 替换当前进程为Screen命令,原脚本进程会终止 os.execvp('screen', screen_cmd) if __name__ == '__main__': if not is_in_screen(): print("不在Screen会话中,将重启到Screen运行...") restart_in_screen() # ---------------------- 以下是你的业务代码 ---------------------- print("已在Screen会话中运行,开始执行长时间任务") import time for count in range(100): print(f"任务进度: {count+1}/100") time.sleep(1)
关键细节说明
检测Screen会话的正确方式
不要用解析进程树的方式,直接读取STY环境变量是Screen官方推荐的检测方法,简单可靠。为什么用
os.execvp而不是subprocessos.execvp会直接替换当前脚本进程,不会留下额外的父进程,避免出现脚本重复运行的问题;subprocess.run会创建子进程,原脚本进程仍会继续执行,可能导致逻辑混乱。
Screen参数的作用
-D -m:强制启动一个分离的Screen会话,即使当前已经有其他会话存在,也能确保脚本在后台稳定运行;-S long_running_script:自定义会话名称,后续可以用screen -r long_running_script快速重新连接查看输出。
参数传递的正确性
- 用
sys.executable获取当前Python解释器路径,避免硬编码python/python3导致的环境差异; - 直接拼接
sys.argv保留所有原启动参数,确保重启后的脚本和原调用逻辑一致。
- 用
你之前写法的问题
- 使用
subprocess.run(..., shell=True)时,列表格式的参数会被当作单个字符串传递给shell,导致Screen无法正确解析命令; os.execv的参数构造错误:你把python + " " + sys.argv[0]作为单个参数传递,Screen会把这个整串当作一个命令去执行,而不是拆分出Python解释器和脚本路径,自然无法运行。
内容的提问来源于stack exchange,提问作者carmiac
相关产品推荐
相关产品推荐

