繁体   English   中英

为什么在 Python 中使用子进程调用“ssh -f -N 主机名”时 PID 会发生变化,以及如何在程序结束时可靠地终止它?

[英]Why does the PID change when "ssh -f -N hostname" is called using subprocess in Python, and how can I terminate it reliably when my program ends?

我需要通过代理连接到目标设备以在目标上执行一些命令。 为此,我需要打开到代理的 SSH 隧道,然后使用 Python 库通过 SSH 与目标进行交互。 该库无法容纳代理连接。 当我直接使用我的 shell 来启动隧道,然后使用 Python 库与目标交互时,这个概念有效。 我现在需要将 shell 命令移动到我的 Python 程序中。

我尝试使用带有以下代码的子进程打开 SSH 隧道:

    config_file = "path/to/config"
    cmd = shlex.split(f"ssh -f -N jumphost-tunnel -F {config_file}")
    process = subprocess.Popen(
        cmd, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
    )

这会造成两个问题。

问题一

当我调用process.pid ,PID 与我执行ps aux | grep ssh时看到的不同ps aux | grep ssh ps aux | grep ssh并记下操作系统上的 PID。 它是关闭的1(即:PID从subprocess.pid44196从PID ps aux44197 )。

我想了解为什么 PID 关闭了 1。是不是因为使用ssh -f调用时 SSH 进程被置于后台?

问题二

它留下了一个僵尸 SSH 隧道,因为由于不知道隧道命令的 PID,我无法使用subprocess.kill()终止隧道。

程序完成后,如何安全可靠地终止 SSH 隧道? 对于某些背景,我需要通过隧道连接到代理服务器并通过 SSH 在目标设备上执行命令。 目标设备是瞻博网络 SRX。 我正在使用 PyEZ-junos 库与之交互。 该库在ProxyCommand使用ProxyCommand与 Junos 设备交互,但库实现不使用 OpenSSH 提供的ProxyCommandProxyJump指令,因此调用ProxyJump以启动到代理服务器的隧道。 我不想更改 PyEZ 库的内部结构来解决隧道问题。

我还没有检查过,但如果一个 PID 不是由 ssh 通过派生一个新进程并让原始进程退出来“背景化”本身引起的,我会感到惊讶。

我不认为你真的需要 -f 标志。 subprocess.Popen 无论如何都会启动一个新进程。

暂无
暂无

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

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