如何使用Python的Popen执行scp且无需手动输入密码?
问题:如何实现无需手动输入密码执行scp操作(不使用密钥认证)
我写了如下test.py脚本,目的是将test_file复制到位于10.0.0.2的远程目录/home/user/data,使用用户user的登录凭证,要求必须使用scp且不采用密钥认证方式,但脚本无法自动完成密码输入,请问该怎么修改?
原脚本代码:
#!/usr/bin/env python2 from subprocess import Popen, PIPE, STDOUT proc = Popen(['scp', 'test_file', 'user@192.168.120.172:/home/user/data'], stdout=PIPE, stdin=PIPE, stderr=STDOUT) out, err = proc.communicate(input='userpass\n') print('stdout: ' + out) print('stderr: ' + str(err))
解答
你的原脚本没法自动输入密码,核心原因是scp并不会从标准输入(stdin)读取密码,它是直接从终端设备读取的,所以直接用proc.communicate(input='userpass\n')传递密码根本没用。下面给你两种可靠的实现方式,都是无需手动输密码且不依赖密钥认证的:
方法1:用sshpass工具(简单直接)
sshpass是专门为ssh/scp这类需要终端输入密码的工具设计的小工具,能帮你自动传递密码。
步骤1:安装sshpass
根据你的系统选择安装命令:
- Debian/Ubuntu系:
sudo apt-get install sshpass - RHEL/CentOS系:
sudo yum install sshpass
步骤2:修改Python脚本
把scp命令用sshpass包裹,通过-p参数传入密码,同时注意把原脚本里写错的目标IP(192.168.120.172)改成你实际需要的10.0.0.2:
#!/usr/bin/env python2 from subprocess import Popen, PIPE, STDOUT import os # 建议从环境变量读取密码,不要硬编码(更安全) password = os.environ.get('SCP_PASSWORD', 'userpass') proc = Popen( ['sshpass', '-p', password, 'scp', 'test_file', 'user@10.0.0.2:/home/user/data'], stdout=PIPE, stderr=STDOUT, shell=False ) out, _ = proc.communicate() print('stdout: ' + out)
注意:硬编码密码在脚本里有安全风险,建议通过环境变量传递,比如执行脚本前先设置:
export SCP_PASSWORD="userpass"
方法2:用Python的pexpect库(更贴合Python生态)
pexpect是Python的第三方库,专门用来处理交互式命令行程序,能精准匹配scp的密码提示并自动响应。
步骤1:安装pexpect
pip install pexpect
步骤2:编写脚本
#!/usr/bin/env python2 import pexpect import os # 从环境变量读取密码,避免硬编码 password = os.environ.get('SCP_PASSWORD', 'userpass') # 定义scp命令 scp_cmd = 'scp test_file user@10.0.0.2:/home/user/data' # 启动交互式进程 child = pexpect.spawn(scp_cmd) # 匹配scp的密码提示(不同系统可能略有差异,比如"Password:"或者"password:") child.expect(r'[Pp]assword:') # 发送密码并换行 child.sendline(password) # 等待命令执行完成,获取输出 child.expect(pexpect.EOF) output = child.before.decode('utf-8') print('执行输出:\n' + output)
这种方法更灵活,能适配不同系统的密码提示格式,而且不需要额外安装系统级工具,完全在Python环境内解决。
内容的提问来源于stack exchange,提问作者rbaleksandar
相关产品推荐
相关产品推荐

