2015-03-03 255 views
2

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

proc = pexpect.spawn('sshfs %[email protected]%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 %[email protected]%s:%s...', shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)  
proc.stdin.write('thepassphrase'+'\n') 
proc.stdin.flush() 

当然,我已经尝试了很多这种轻微的变化没有成功,当然,当我手动运行命令时,命令运行良好。

更新3/3: 今天我也有手动编译和安装在RHEL 6.6的ssh看是否这是造成问题,但这个问题即使有新的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版本工作,我会真的。

+0

呃......如果你正在存储PK的加密密钥,明文,为什么要加密密钥呢? – SingleNegationElimination 2015-03-03 03:51:49

+0

这是用户在线输入密码字段中的密码的Web应用程序的一部分。密码只能在RAM中“保存”不到一分钟,我猜这不是绝对的最好,但似乎不是一个重大的安全问题。 – user2205380 2015-03-03 14:18:50

+1

“ssh-agent”对你来说不是一个可行的解决方案吗? – twalberg 2015-03-09 17:17:53

回答

1

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

passphrase = 'some passphrase' 
cmd = "sudo -H -u somebody sshfs [email protected]:/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