我需要使用密码从命令行运行SCP。
具体来说,这是因为我需要使用Python库Fabric将一台远程计算机SCP连接到另一台远程计算机,而文件不通过本地计算机(这是一个大文件,两台远程计算机连接速度更快)除了我的本地机器之外,它们之间有任何一个。)两台远程机器正在运行CentOS。
但就主要问题而言,这些细节都不是特别重要。
答案 0 :(得分:0)
首先,详细说明执行此操作的安全隐患,只需运行ps -ww -fp <pid>
即可轻松查看命令行参数。此漏洞是scp不允许在命令行上传入密码的原因。
因此,请确保您可以运行该命令的任何人都能以纯文本格式查看密码。
SCP的作者认为你是如此愚蠢,以至于你会滥用在命令行上输入密码的能力。另一方面,我相信你已经被充分警告了,如果你想这样做,你就不应该被阻止。
在实际解决方案上:
您需要在应运行SCP的计算机上安装expect
。
在我使用Python库Fabric控制运行CentOS的机器的特定情况下,我运行以下命令来安装它:
from fabric.operations import sudo
sudo('yum -y install expect')
要直接从CentOS上的命令行运行,只需执行:
$ yum -y install expect
(我假设你知道你在自己的操作系统上与yum等价的东西。)
预计安装后,您可以像这样运行SCP:
expect -c
'spawn scp <copy-from-username>@<copy-from-address>:<copy-from-path> <copy-to-path>;
expect "*?es??o*" {send "yes\r"; exp_continue}
"*?assword:" {send "<copy-from-password>\r"};
interact'
我已将其格式化以便于阅读,但您可以使用空格替换换行符/标签,它们的工作方式也相同。
第一行表示以下是expect命令(不是其余的单引号)。
第二行产生了SCP进程。
第三行开始定义要在输出中查找的内容,并说"*?es??o*"
应得到yes
的响应。 \r
对于发送输入击键非常重要。时髦模式旨在捕获类似(Yes/No)
的内容,如果它询问是否继续建立连接。 exp_continue
告诉他们在回复此邮件后仍未完成。
第四行有另一个要寻找的东西,该行中的模式旨在捕获Password:
,无论p是否为大写。确保在密码后面加\r
,否则将不会发送密码。此行没有exp_continue
,因为一旦expect发送了密码,我们就不再需要了。
第五行interact
非常重要,因为没有它就行不通。我对它究竟是做什么有点模糊,但我的理解是spawn
直到那条线被击中。我想这很重要,因为你需要在运行spawn之前定义期望,否则生成的进程可能会传递任何期望的内容,这可能会破坏整个目的。这是我的理解 - 我可能是错的。无论哪种方式,脚本都可以工作。
这是我用Fabric编写的Python函数完整地执行此操作:
def putFromFileRepository(repoIP, repoUsername, repoPassword, repoPath, putPath):
from fabric.operations import sudo
# There are security implications from passing a password as an argument
# on the command line, namely that command line arguments can be easily seen
# from anywhere via 'ps -ww -fp <pid>'.
# Thus scp doesn't allow passwords to be passed on the command line.
# We'll install expect to make it possible.
sudo('yum -y install expect')
repoStr = repoUsername + '@' + repoIP + ':' + repoPath
# expect has alien syntax - explained inline below.
# see man expect for more details.
sudo("expect -c 'spawn scp " + repoStr + ' ' + putPath + '; ' # Run SCP when started.
+ 'expect "*?es??o*" {send "yes\r"; exp_continue} ' # Reply yes to yes/no questions.
+ '"*?assword:" {send "' + repoPassword + '\r"}; ' # Give password when prompted.
+ "interact'") # Start.