使用Python subprocess模块在远程服务器指定工作目录的方法
问题与解决:通过subprocess+SSH访问远程非/home目录文件
问题描述
在Python2环境下,使用subprocess模块通过SSH连接远程服务器时,能正常列出home目录的文件,但访问home/child/child2子目录时遇到问题:
- 尝试传入
cd和ls作为独立参数,代码运行但无返回结果 - 使用
cwd参数指定路径,报错OSError: [Errno 2] No such file or directory: 'child/child2/'
用户的错误代码示例:
错误代码1:拆分cd和ls为独立参数
import sys,subprocess p = subprocess.Popen(['ssh','username@hostip', 'cd home/child/child2', 'ls -a'], stdout = subprocess.PIPE, stderr = subprocess.PIPE) out, err = p.communicate() out.decode("utf-8").split('\n')[:-1] print(out) print(err)
错误代码2:使用本地cwd参数
import sys,subprocess p = subprocess.Popen(['ssh','username@hostip', 'ls -a'], cwd = 'child/child2/', stdout = subprocess.PIPE, stderr = subprocess.PIPE) out, err = p.communicate() out.decode("utf-8").split('\n')[:-1] print(out) print(err)
错误原因
- 拆分命令的问题:SSH接收的是单个完整的shell命令字符串,不是多个独立命令。把
cd home/child/child2和ls -a拆成两个参数,SSH会把前者当作要执行的命令,后者当作远程主机的额外参数,实际只执行了cd,没有执行ls。 - cwd参数的作用范围:
cwd是控制本地Python进程的工作目录,不是远程服务器的目录,所以本地找不到child/child2才会报错。
正确实现方式
方案1:合并命令为单个字符串
用&&连接cd和ls,确保远程shell先切换目录成功,再执行ls:
import sys, subprocess p = subprocess.Popen( ['ssh', 'username@hostip', 'cd home/child/child2 && ls -a'], stdout=subprocess.PIPE, stderr=subprocess.PIPE ) out, err = p.communicate() # 注意编码是utf-8(之前的utd-8是笔误) file_list = out.decode("utf-8").split('\n')[:-1] print(file_list) print(err)
方案2:直接指定ls的目标路径
不需要切换目录,直接让ls访问目标路径,更简洁:
import sys, subprocess p = subprocess.Popen( ['ssh', 'username@hostip', 'ls -a home/child/child2'], stdout=subprocess.PIPE, stderr=subprocess.PIPE ) out, err = p.communicate() file_list = out.decode("utf-8").split('\n')[:-1] print(file_list) print(err)
额外提示
- 路径可以用
~/child/child2替代home/child/child2,更严谨地指向当前用户的home子目录 - 如果需要下载文件,可用
scp命令替换ls,示例:# 下载远程文件到本地指定路径 p = subprocess.Popen( ['scp', 'username@hostip:~/child/child2/your_file.txt', './local_save_path/'], stdout=subprocess.PIPE, stderr=subprocess.PIPE ) out, err = p.communicate()
内容的提问来源于stack exchange,提问作者btmc872
相关产品推荐
相关产品推荐

