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

发布于 2024-10-16 23:37:07 字数 1181 浏览 1 评论 0原文

我需要具有本质上模拟用户使用 ssh 创建端口转发的功能。所以,本质上应该是这样的: - 执行 ssh -f -N -L 10000:gateway:11000 localhost - 如果该命令有输出,则向用户显示并泵送用户的输入作为响应 - 结束 我在下面想出的代码几乎满足了我的需要:

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

但问题是它永远不会完成。我看到命令已执行并创建了转发隧道,但 communications() 仍然卡住。我可以使用 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 命令一起使用,因此它应该分叉连接。有没有办法在 communications() 完成时中断它,或者是否有更优雅的解决方案?

预先感谢您的任何意见/建议/评论。

I need to have functionality that would essentially emulate user creating a port forwrding with ssh. So, essentially that should work like that:
- execute ssh -f -N -L 10000:gateway:11000 localhost
- if there is an output from that command, show to the user and pump user's input as a response
- finish
The code I came up with below, almost does what I need:

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

But the problem is it never finishes. I see the command is executed and forwarding tunnel is created but communicate() is still stuck. I can break out of that with Ctrl+C and get this:

    ^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

Since i use -f with ssh command, it should fork the connection. Is there a way to interrupt communicate() when it is done or is there more elegant solution?

Thank you in advance for any advices/suggestions/comments.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

黎歌 2024-10-23 23:37:07

我想解决方案很简单

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()

I guess the solution was pretty easy

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()
︶ ̄淡然 2024-10-23 23:37:07

当尝试设置 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

这样,即使没有从 stdout 或 stderr 读取任何内容,communicate() 函数也不会阻止进程。

I had a relative problem when tried to set an ssh tunnel, communicate() would hang on forever, I have found that it reads from the stderr and stdout, so if your command didn't write anything to the stderr for example, then it will hang because it's waiting to read something from the stderr (fd = 2).
So as a solution you could use 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

That way the communicate() function will not block the process, even if there is nothing to read from stdout or stderr.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文