如何用Python原生实现本地与远端文件传输并获取进程实时状态
问题根因
你之前的写法失败主要有两个核心问题:
- 第一种写法没有给
subprocess.Popen加shell=True参数,默认情况下subprocess不会解析shell语法(包括管道符、引号、&&逻辑符都不会处理),同时你给出的命令字符串还遗漏了末尾的闭合双引号 - 第二种写法用列表传参时错误地把后续管道逻辑都当成了
tar的参数,列表传参要求每个命令参数单独作为列表元素,且默认不会解析管道等shell语法,完全无法实现你要的跨进程管道传输逻辑
实现方案
方案1:直接启用shell解析(最简实现)
如果你能保证命令中的路径、地址等参数都是可控的,不会有注入风险,直接加shell=True即可完美适配你原来的shell命令逻辑,同时可以拿到进程状态:
import subprocess cmd = 'tar zcf - somefolder/ | ssh user@server "cd /path/to/remote && tar zxf -"' # 启用shell解析管道、引号等语法 p = subprocess.Popen(cmd, shell=True) # 获取实时状态示例: while True: exit_code = p.poll() if exit_code is None: print("进程仍在运行") # 这里可以自定义轮询间隔 import time time.sleep(1) else: print(f"进程执行完成,退出码:{exit_code}") break
你也可以用os.waitpid(p.pid, 0)来阻塞等待进程结束,和你之前的需求完全兼容。
方案2:无shell模式手动拼接管道(更安全)
如果担心shell注入风险,可以不用启用shell解析,手动创建本地tar进程和远端ssh进程,把两个进程的输入输出流对接,逻辑更可控:
import subprocess # 本地打包进程 tar_proc = subprocess.Popen( ["tar", "zcf", "-", "somefolder/"], stdout=subprocess.PIPE ) # 远端解压进程 ssh_proc = subprocess.Popen( ["ssh", "user@server", "cd /path/to/remote && tar zxf -"], stdin=tar_proc.stdout ) # 关闭tar进程的stdout副本,避免IO阻塞 tar_proc.stdout.close() # 多进程状态获取 while True: tar_exit = tar_proc.poll() ssh_exit = ssh_proc.poll() if tar_exit is not None and ssh_exit is not None: print(f"打包进程退出码:{tar_exit},远端解压进程退出码:{ssh_exit}") break import time time.sleep(1)
两种方案都不需要引入第三方库,完全基于Python标准库实现。
内容的提问来源于stack exchange,提问作者user
相关产品推荐
相关产品推荐

