从用Python编写的HTTP RPC服务器启动SSH隧道时遇到了麻烦。
有一个基于Python的BaseHTTPServer用Python编写的简单HTTP RPC服务器。 作为其中一项服务的一部分,我想从RPC服务器启动到远程机器的SSH隧道。我使用os.system在RPC调用
调用的Python脚本中启动SSH隧道os.system("ssh -f -n -N -L 127.0.0.1:%d:localhost:%d user@%s" % (6800, 9000, "remote.machine"))
乍一看,当隧道启动时,所有人似乎都很好,我可以使用它,但有一点我注意到了。除了侦听端口6800之外,SSH也开始侦听端口8001(运行HTTP RPC服务器的端口)。
以下是关于RPC服务器和SSH的lsof输出:
rpc.py 27763 usern 5u IPv4 102130428 TCP 127.0.0.1:8001 (LISTEN)
ssh 1951 usern 14u IPv4 102149728 TCP 127.0.0.1:6800 (LISTEN)
ssh 1951 usern 5u IPv4 102130428 TCP 127.0.0.1:8001 (LISTEN)
一切正常,直到RPC服务器重启。在重新启动期间,RPC服务器被强制关闭与侦听套接字的连接,但SSH的连接仍然打开,RPC服务器无法再次在同一端口上启动。
似乎SSH隧道也以某种方式将自己与RPC服务器的侦听套接字的fd相关联。
任何人都可以提示如何从脚本设置SSH隧道,只需要监听假定的端口(本例中为6800)。
答案 0 :(得分:2)
使用subprocess.Popen()并设置close_fds = True(在Python 2.4及更高版本中可用),而不是os.system()。
import subprocess
subprocess.Popen("ssh -f -n -N -L 127.0.0.1:%d:localhost:%d user@%s" % (6800, 9000, "remote.machine"), shell=True, close_fds=True)
理论上,我相信你也应该能够在调用os.system()之前使用fcntl将侦听套接字的文件描述符设置为close-on-exec(FD_CLOEXEC)。
答案 1 :(得分:1)
您是否考虑过将paramiko用于SSH? (取决于PyCrypto,但其他纯Python)
这样可以简化管理连接,并且根据服务器处理套接字的方式,您可以设置paramiko Channel,然后让服务器将其视为任何其他侦听套接字。
(在paramiko中,传输对象代表基本的SSH2连接,并且对于每个传输,您可以创建多个Channel对象,每个对象都充当常规Python套接字的替代品)
以下是一些资源,以供您查看:
答案 2 :(得分:0)
我怀疑这与分叉有关,然后告诉ssh从调用进程(“-f”)分离。
另外,不确定这是否会有所帮助,但如果你的python足够现代,你应该真正使用子进程模块。