如何通过Python脚本在Gnome Terminal中运行命令并等待进程终止
解决方案
方案1:利用Gnome Terminal的--wait参数
Gnome Terminal 3.28及以上版本支持--wait参数,启用后终端会保持打开状态,直到内部执行的命令完全结束。你可以直接让终端运行目标可执行文件,通过wait()等待终端退出,间接实现等待目标程序完成的效果。
示例代码:
import subprocess from concurrent.futures import ThreadPoolExecutor def run_in_terminal(executable_path): # 启动Gnome Terminal并执行目标程序,--wait参数让终端等待程序结束 proc = subprocess.Popen([ "gnome-terminal", "--wait", "--", # 分隔终端自身参数与要执行的命令 executable_path ]) proc.wait() # 程序执行完成后的后续操作 print(f"{executable_path} 已执行完毕") if __name__ == "__main__": # 替换为你的可执行文件路径列表 executables = ["./test1", "./test2", "./test3"] with ThreadPoolExecutor(max_workers=len(executables)) as executor: executor.map(run_in_terminal, executables)
如果可执行文件需要传递参数,直接追加到executable_path后即可,例如:"./test1", "arg1", "arg2"。
方案2:通过PID监控目标进程
如果你的Gnome Terminal版本不支持--wait参数,可以让终端启动程序时将进程PID写入临时文件,再由Python脚本读取PID并监控进程状态。
示例代码:
import subprocess import os import tempfile from concurrent.futures import ThreadPoolExecutor import time def run_and_monitor(executable_path): # 创建临时文件用于存储进程PID with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmpf: tmp_path = tmpf.name # 启动终端,让目标程序将自身PID写入临时文件后执行 subprocess.Popen([ "gnome-terminal", "--", "bash", "-c", f"echo $$ > {tmp_path}; exec {executable_path}" ]) # 等待临时文件生成并读取PID while not os.path.exists(tmp_path): time.sleep(0.1) with open(tmp_path, 'r') as f: pid = int(f.read().strip()) os.unlink(tmp_path) # 读取后删除临时文件 # 监控进程直到结束 try: os.waitpid(pid, 0) except ChildProcessError: # 处理进程已提前结束的情况 pass print(f"{executable_path} 已执行完毕") if __name__ == "__main__": executables = ["./test1", "./test2", "./test3"] with ThreadPoolExecutor(max_workers=len(executables)) as executor: executor.map(run_and_monitor, executables)
这里通过exec命令让目标程序替换当前shell进程,确保$$获取到的就是目标程序的真实PID,避免监控到shell进程而非目标进程的问题。
方案3:使用screen工具(备选)
如果上述方案都不适用,可以借助screen工具在终端中启动程序,再通过PID监控进程状态:
import subprocess import os from concurrent.futures import ThreadPoolExecutor def run_with_screen(executable_path): # 用screen创建后台会话并启动程序 session_name = f"exec_session_{os.path.basename(executable_path)}" subprocess.Popen([ "screen", "-dmS", session_name, executable_path ]) # 获取screen会话对应的进程PID pid = int(subprocess.check_output([ "pgrep", "-f", f"screen.*{session_name}" ]).strip()) os.waitpid(pid, 0) print(f"{executable_path} 已执行完毕") if __name__ == "__main__": executables = ["./test1", "./test2", "./test3"] with ThreadPoolExecutor(max_workers=len(executables)) as executor: executor.map(run_with_screen, executables)
该方案需要系统预先安装screen工具,且PID匹配逻辑可能需要根据实际情况调整,可靠性略低于前两种方案。
内容的提问来源于stack exchange,提问作者ryan2900
相关产品推荐
相关产品推荐

