如何使用pexpect自动输入ssh私钥密码

时间:2015-03-03 03:35:01

标签: python linux ssh redhat sshfs

我以前为linux env编写了一个程序,它自动运行SSHFS二进制文件作为用户并输入存储的ssh私钥密码。 (公共一半已经在远程服务器上)我在一台服务器上使用简单的pexpect命令。 (Ubuntu服务器14.04,ssh版本6.6,sshfs版本2.5)但是当应用程序被移动到redhat机器(RHEL6.5,ssh版本5.3,sshfs版本2.4)时,这个程序的单个部分被证明是一个问题。简单的一步一直让我疯狂,所以现在我转向这个社区寻求支持。我的原始代码(简化)看起来像这样:

proc = pexpect.spawn('sshfs %s@%s:%s...') #many options, unrelated
proc.expect([pexpect.EOF, 'Enter passphrase for key.*', pexpect.TIMEOUT], timeout=30)
if proc.match_index == 1:
    proc.sendline('thepassphrase')

在ubuntu上按预期运行,但不是rhel。我也尝试过管道到子进程的回退方法,但也没有太大的成功。

proc = subprocess.Popen('sshfs %s@%s:%s...', shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)    
proc.stdin.write('thepassphrase'+'\n')
proc.stdin.flush()

当然,我尝试了很多这方面没有成功的细微变化,当然,当我手动运行时,命令运行正常。

更新3/3 : 我今天也在rhel中手动编译并安装了ssh 6.6,看看是否会导致问题,但即使使用新的ssh二进制文件,问题仍然存在。

更新3/9

今天我找到了一个可行的特定解决方案,但我对其他许多不同的解决方案不起作用的事实感到不满意,我仍然在寻找答案。这是迄今为止我能做的最好的事情:

proc = subprocess.check_call("sudo -H -u %s ssh-keygen -p -P %s -N '' -f %s" % (user, userKey['passphrase'], userKey['path']), shell=True)
time.sleep(2)

proc = subprocess.Popen(cmd, shell=True)

proc.communicate()

time.sleep(1)
proc = subprocess.check_call("sudo -H -u %s ssh-keygen -p -P '' -N %s -f %s" % (user, userKey['passphrase'], userKey['path']), shell=True)

从密钥中删除密码,安装驱动器,然后重新添加密钥。显然我不喜欢这个解决方案,但它必须要做,直到我能够深入到底。

更新3/23

好吧,由于我的愚蠢,直到现在我还没有看到这个方法的直接问题,现在我又回到了绘图板。虽然这种解决方法在第一次连接时确实有效,但-o重新连接显然会失败,因为sshfs不知道要重新连接的密码。这意味着这个解决方案不再可行,如果有人知道如何让pexpect版本正常工作,我真的会这么做。

1 个答案:

答案 0 :(得分:1)

在与开发人员亲自交谈之后,我已经确定这是一个已知的错误,并且没有一个正确的方法以问题中指定的相同样式运行命令。然而,开发人员很快就提出了一个同样有用的方法,它涉及产生另一个终端进程。

passphrase = 'some passphrase'
cmd = "sudo -H -u somebody sshfs somebody@somewhere:/somewhere-else /home/somebody/testmount -o StrictHostKeychecking=no -o nonempty -o reconnect -o workaround=all -o IdentityFile=/somekey -o follow_symlinks -o cache=no"

bash = pexpect.spawn('bash', echo=False)
bash.sendline('echo READY')
bash.expect_exact('READY')
bash.sendline(cmd)
bash.expect_exact('Enter passphrase for key')
bash.sendline(passphrase)
bash.sendline('echo COMPLETE')
bash.expect_exact('COMPLETE')
bash.sendline('exit')
bash.expect_exact(pexpect.EOF)

我已经测试过这个解决方案,它已经成为一个很好的解决方案而没有太多的额外开销。您可以查看他的完整回复here