繁体   English   中英

python subprocess.Popen 和 ssh 后台端口转发

[英]python subprocess.Popen and ssh port forwarding in the background

我需要具有本质上模拟用户使用 ssh 创建端口转发的功能。因此,本质上应该像这样工作: - 执行ssh -f -N -L 10000:gateway:11000 localhost - 如果该命令中有 output ,向用户显示并将用户的输入作为响应 - 完成我在下面想出的代码几乎可以满足我的需要:

    ssh_proc = Popen(['ssh', '-f', '-N', '-L', '10000:gateway:11000', 'localhost'], stdin=PIPE, stdout=PIPE)
stdoutdata, stderrdata = ssh_proc.communicate()

但问题是它永远不会结束。 我看到命令已执行并创建了转发隧道,但 communicate() 仍然卡住。 我可以使用 Ctrl+C 打破它并得到这个:

    ^CTraceback (most recent call last):
  File "sshman.py", line 278, in <module>
    add(args.remote_host, args.remote_port, args.local_port, args.local_host)
  File "sshman.py", line 125, in add
    stdoutdata, stderrdata = ssh_proc.communicate()
  File "/usr/lib64/python2.7/subprocess.py", line 740, in communicate
    return self._communicate(input)
  File "/usr/lib64/python2.7/subprocess.py", line 1256, in _communicate
    stdout, stderr = self._communicate_with_poll(input)
  File "/usr/lib64/python2.7/subprocess.py", line 1310, in _communicate_with_poll
    ready = poller.poll()
KeyboardInterrupt

由于我将 -f 与 ssh 命令一起使用,因此它应该分叉连接。 有没有办法在完成时中断 communicate() 或者有更优雅的解决方案?

提前感谢您的任何意见/建议/意见。

我想解决方案很简单

ssh_proc = Popen(['ssh', '-f', '-N', '-L', '10000:gateway:11000', 'localhost'], stdin=PIPE, stdout=PIPE)
stat = ssh_proc.poll()
while stat == None:
    stat = ssh_proc.poll()

我在尝试设置 ssh 隧道时遇到了一个相对的问题,communicate() 会永远挂起,我发现它从 stderr 和 stdout 读取,所以如果你的命令没有向 stderr 写入任何东西,那么它将挂起,因为它正在等待从 stderr (fd = 2) 中读取内容。 因此,作为解决方案,您可以使用 os.set_blocking(ssh_proc.stderr.fileno(), False):

# Start the process.
ssh_proc = Popen(...)
# Wait till it's done.
ssh_proc.wait()
# Disable block for read.
os.set_blocking(ssh_proc.stderr.fileno(), False)
os.set_blocking(ssh_proc.stdout.fileno(), False)
# Read stdout and stderr.
err = ssh_proc.stderr.readlines()
out = ssh_proc.stdout.readlines()
# Print stderr and stdout.
if out:
    out = out[0]
    print(out)
if err:
    err = err[0]
    print(err)
if cmd.returncode == 0:
    return 0

这样 communicate() function 就不会阻塞进程,即使没有任何东西可以从 stdout 或 stderr 读取。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM