基于Python Paramiko通过SCP在两台远程Linux服务器间传输文件
嘿,我来帮你解决这个跨服务器中转传文件的需求!刚好你已经有Paramiko的基础,咱们直接上实用解决方案~
解决方案:通过Server B中转实现文件传输(仅密码认证)
先明确你的核心场景:
- Server A:构建机,运行部署代码
- Server B/C:Linux服务器,仅支持密码登录(无密钥)
- 目标:从Server A出发,先SSH到Server B,再将文件从Server B复制到Server C
下面提供两种可行的实现方式,你可以根据实际需求选择:
方式一:在Server B上执行带密码的scp命令(最直接)
核心思路:让Server A通过Paramiko连接到Server B,然后在Server B的会话中执行scp命令,用sshpass工具自动输入Server C的密码,避免交互式输入提示。
步骤1:确保Server B安装sshpass
如果Server B还没装sshpass,可以先通过Paramiko执行安装命令(根据系统选择对应命令):
import paramiko def create_ssh_client(server, port, user, password): client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(server, port, user, password) return client # 连接Server B ssh_b = create_ssh_client("server_b_ip", 22, "b_username", "b_password") # Debian/Ubuntu系统安装sshpass(CentOS/RHEL替换为sudo yum install -y sshpass) install_cmd = "sudo apt-get update && sudo apt-get install -y sshpass" # 如果需要sudo密码,改成:sshpass -p 'b_sudo_password' sudo -S apt-get install -y sshpass stdin, stdout, stderr = ssh_b.exec_command(install_cmd) exit_status = stdout.channel.recv_exit_status() if exit_status == 0: print("sshpass安装成功") else: print(f"安装失败:{stderr.read().decode('utf-8')}") ssh_b.close()
步骤2:完整传输代码
import paramiko def create_ssh_client(server, port, user, password): client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(server, port, user, password) return client # 服务器配置信息 SERVER_B = { "host": "server_b_ip", "port": 22, "user": "b_username", "pass": "b_password" } SERVER_C = { "host": "server_c_ip", "port": 22, "user": "c_username", "pass": "c_password" } # 文件路径配置:Server B上的源文件,Server C上的目标路径 SOURCE_ON_B = "/path/to/your/file/on/server_b" DEST_ON_C = "/path/to/destination/on/server_c" # 1. 连接到Server B ssh_b = create_ssh_client(**SERVER_B) # 2. 构造自动输入密码的scp命令 scp_cmd = f"sshpass -p '{SERVER_C['pass']}' scp -P {SERVER_C['port']} {SOURCE_ON_B} {SERVER_C['user']}@{SERVER_C['host']}:{DEST_ON_C}" # 3. 执行命令并检查结果 stdin, stdout, stderr = ssh_b.exec_command(scp_cmd) exit_status = stdout.channel.recv_exit_status() if exit_status == 0: print("✅ 文件从Server B复制到Server C成功!") else: print(f"❌ 复制失败,错误信息:{stderr.read().decode('utf-8')}") # 关闭连接 ssh_b.close()
方式二:通过端口转发实现跳板传输(更灵活)
如果需要从Server A直接把文件通过Server B中转到Server C(不用先存到B的磁盘),可以用Paramiko的端口转发功能,把Server A的本地端口映射到Server C的22端口,然后直接用SCPClient传输。
import paramiko from scp import SCPClient # 跳板服务器(Server B)配置 JUMP_SERVER = { "host": "server_b_ip", "port": 22, "user": "b_username", "pass": "b_password" } # 目标服务器(Server C)配置 TARGET_SERVER = { "host": "server_c_ip", "port": 22, "user": "c_username", "pass": "c_password" } # Server A本地要传输的文件路径 LOCAL_FILE = "/path/to/file/on/server_a" # Server C上的目标路径 DEST_ON_C = "/path/to/destination/on/server_c" # 1. 连接到Server B作为跳板 jump_client = paramiko.SSHClient() jump_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) jump_client.connect(**JUMP_SERVER) # 2. 创建端口转发:将本地端口映射到Server C的22端口 transport = jump_client.get_transport() dest_addr = (TARGET_SERVER["host"], TARGET_SERVER["port"]) local_addr = ("127.0.0.1", 0) # 自动分配本地端口 channel = transport.open_channel("direct-tcpip", dest_addr, local_addr) # 3. 通过转发的端口连接Server C target_client = paramiko.SSHClient() target_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) target_client.connect( hostname="127.0.0.1", port=channel.get_local_port(), username=TARGET_SERVER["user"], password=TARGET_SERVER["pass"], sock=channel ) # 4. 用SCPClient传输文件 with SCPClient(target_client.get_transport()) as scp: scp.put(LOCAL_FILE, DEST_ON_C) print("✅ 文件通过Server B中转到Server C成功!") # 关闭所有连接 target_client.close() jump_client.close()
注意事项
- 安全性提示:明文传递密码存在一定风险,如果是生产环境,建议尽量切换到密钥对认证;如果必须用密码,确保服务器处于可信网络环境中。
- 若密码包含特殊字符(比如
!、$),需要用反斜杠转义,或者保持代码中的单引号包裹方式来避免解析错误。
内容的提问来源于stack exchange,提问作者Pankaj Kumar
相关产品推荐
相关产品推荐

