通过ssh隧道传输TCP端口而不阻塞
我正在尝试通过pexpect设置一个ssh隧道,使用以下代码:
#!/bin/env python2.4
import pexpect, sys
child = pexpect.spawn('ssh -CfNL 0.0.0.0:3306:127.0.0.1:3306 user@server.com')
child.logfile = sys.stdout
while True:
code = child.expect([
'Are you sure you want to continue connecting \(yes/no\)\?',
'password:',
pexpect.EOF,
pexpect.TIMEOUT
])
if code == 0:
child.sendline('yes')
elif code == 1:
child.sendline('passwordhere')
elif code == 2:
print ".. EOF"
break
elif code == 3:
print ".. Timeout"
break
我希望在发送完密码并成功建立ssh隧道后,while循环能够退出,这样我就可以继续处理其他业务逻辑。
但是,上面的代码会在ssh隧道建立后仍然阻塞,直到超时(大约30秒)。
有没有人能给我一些建议,告诉我怎么避免这种阻塞?
1 个回答
3
我觉得最简单的解决办法是使用ssh主机密钥认证,然后把ssh
放到后台运行,方法是加上&
。这其实是个很基础的做法,但你可以进一步改进,比如在完成后结束这个进程。另外,注意我在你的ssh
参数中加了-n
,因为我们是把这个进程放到后台。
import subprocess
USER = 'user'
HOST = 'server.com'
cmd = r"""ssh -CfNnL 0.0.0.0:3306:127.0.0.1:3306 %s@%s &""" % (USER, HOST)
subcmd = cmd.split(' ')
retval = subprocess.Popen(subcmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stat = retval.poll()
while stat == None:
stat = retval.poll()
print "ssh in background"
最后,如果你的ssh_config
里还没有ServerAliveInterval
这个设置,可以考虑这样调用ssh
:ssh -o ServerAliveInterval=30 <other_options_and_args>
。这样可以确保你尽快发现连接丢失,并且防止在不活动时被网络地址转换(NAT)机制给断掉。