我以前为linux env编写过一个程序,该程序以用户身份自动运行sshfs二进制文件,并输入存储的ssh私钥密码短语。(public half已经在远程服务器上)我在一台服务器上使用了简单的pexpect命令。(ubuntu server 14.04,ssh version 6.6,sshfs version 2.5)但是当应用程序被移动到redhat机器(rhel6.5,ssh version 5.3,sshfs version 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:
我今天还手动编译了ssh 6.6并将其安装到rhel中,以查看这是否导致了问题,但是即使使用新的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版本工作,我真的会这么做。

最佳答案:

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

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。