本地Python经SSH跳板机执行SFTP操作的可靠实现方案咨询
问题根因
原来的代码存在两个核心问题:
- 每次调用
exec_command都会创建独立的shell进程,第一次执行的sftp会话和第二次的ls完全无关,第二次的ls是在EC2本地shell执行的,返回的自然是EC2本地的目录内容 - 直接往sftp的stdin写密码的方式不可靠,sftp的密码提示是交互式终端输出,默认
exec_command不分配伪终端,输入的密码不会被sftp进程识别
可靠实现方案
方案1:SSH端口转发(跳板隧道,通用Python方案)
通过paramiko在本地和目标SFTP服务器之间建立跳板隧道,直接在本地操作SFTP,逻辑最清晰,也方便调试:
import paramiko from paramiko import SSHClient, AutoAddPolicy # 1. 先连接跳板EC2 jump_host = '你的EC2公网IP' jump_user = 'EC2登录用户名' jump_key = '/path/to/ec2/ssh/key.pem' # 也可以用密码认证 jump_ssh = SSHClient() jump_ssh.set_missing_host_key_policy(AutoAddPolicy()) jump_ssh.connect(hostname=jump_host, username=jump_user, key_filename=jump_key) # 2. 建立跳板到目标SFTP服务器的端口转发 target_host = '目标SFTP地址' target_port = 22 # SFTP默认端口 local_bind_port = 9999 # 本地随便选一个未占用的端口 # 开通隧道 transport = jump_ssh.get_transport() local_channel = transport.open_channel('direct-tcpip', (target_host, target_port), ('127.0.0.1', local_bind_port)) # 3. 直接通过本地隧道连接SFTP sftp_ssh = SSHClient() sftp_ssh.set_missing_host_key_policy(AutoAddPolicy()) # 连接的时候指向本地转发端口,流量会自动通过跳板发到目标SFTP sftp_ssh.connect(hostname='127.0.0.1', port=local_bind_port, username='SFTP用户名', password='SFTP密码', sock=local_channel) # 4. 正常操作SFTP sftp = sftp_ssh.open_sftp() # 执行ls操作 print(sftp.listdir()) # 其他操作示例 # sftp.put('本地文件路径', '远端存储路径') # sftp.get('远端文件路径', '本地存储路径') # 用完关闭连接 sftp.close() sftp_ssh.close() jump_ssh.close()
如果是Airflow场景,可以把跳板机、SFTP的连接信息都存在Airflow Connections里,读取后替换硬编码的参数即可。
方案2:跳板机执行批处理SFTP命令
如果不需要复杂操作,只是简单执行固定SFTP命令,可以直接把所有SFTP操作拼成一条命令在跳板机执行,不需要维护隧道:
def run_ssh(): hook = SSHHook(ssh_conn_id='xyz').get_conn() # 把所有sftp操作通过管道传给sftp命令,-b参数指定从标准输入读取批处理命令 sftp_cmd = """echo -e "ls\nget remote_file.txt\nquit" | sftp -o StrictHostKeyChecking=no -b - user@host.com << EOF SFTP密码 EOF """ stdin, stdout, stderr = hook.exec_command(sftp_cmd, get_pty=True) # 读取输出 print(stdout.read().decode()) print(stderr.read().decode())
注意这里加了get_pty=True分配伪终端,才能正确输入密码,批处理模式也能保证所有命令都在sftp会话内执行。
注意事项
- 生产环境尽量不要用明文密码做SFTP认证,优先用SSH密钥对,把跳板机的公钥加到目标SFTP服务器的信任列表里,就不需要输入密码,也能避免明文密码泄露风险
- Airflow场景下方案1更稳定,SFTP操作的报错可以直接在本地捕获排查,不需要解析跳板机的远端输出
内容的提问来源于stack exchange,提问作者Ash_s94
相关产品推荐
相关产品推荐

