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

Python 如何使用pexpect自动输入ssh私钥密码短语,python,linux,ssh,redhat,sshfs,Python,Linux,Ssh,Redhat,Sshfs,我之前为LinuxEnv编写了一个程序,它以用户身份自动运行SSHFS二进制文件,并输入存储的ssh私钥密码短语。(公共部分已经在远程服务器上)我在一台服务器上使用了简单的pexpect命令。(Ubuntu服务器14.04,ssh版本6.6,sshfs版本2.5)但当应用程序被移动到redhat机器(RHEL6.5,ssh版本5.3,sshfs版本2.4)时,这个程序的单一部分被证明是一个问题。这一简单的步骤整天都让我发疯,所以现在我转向这个社区寻求支持。我的原始代码(简化)如下所示: proc

我之前为LinuxEnv编写了一个程序,它以用户身份自动运行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版本工作,我真的会这么做

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

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)

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

嗯。。。如果你在明文中存储pk的加密密钥,为什么还要加密密钥呢?这是web应用程序的一部分,用户可以在线在密码字段中输入密码。密码仅在RAM中“存储”不到一分钟,我想这不是绝对最好的,但似乎不是一个主要的安全问题。是否有理由认为
ssh-agent
对您来说不是一个可行的解决方案?我认为,无论密码必须输入一次或多次(尽管我没有测试)类似的问题也会发生。