【问题标题】:Exiting a bash shell that was started with Popen?退出以 Popen 启动的 bash shell?
【发布时间】:2015-04-16 11:04:24
【问题描述】:

我不知道如何关闭通过Popen 启动的bash shell。我在 Windows 上,并试图自动化一些 ssh 的东西。通过 git 附带的 bash shell 更容易做到这一点,因此我通过 Popen 以下列方式调用它:

p = Popen('"my/windows/path/to/bash.exe" | git clone or other commands') 
p.wait() 

问题是在 bash 运行我通过管道输入的命令后,它并没有关闭。它保持打开状态,导致我的wait 无限期阻塞。

我已经尝试在最后串一个“退出”命令,但它不起作用。

p = Popen('"my/windows/path/to/bash.exe" | git clone or other commands && exit') 
p.wait() 

但仍然会无限阻塞等待。完成任务后,它只是坐在 bash 提示符下什么都不做。如何强制关闭?

【问题讨论】:

  • 这里的| 字符是怎么回事?这不是您将命令传递给 bash 的方式。
  • 另外,你为什么要调用 bash,而不是 直接 从 Python 调用你的 git 命令?直接路由使信号处理更容易——这意味着您可以轻松检查或终止 git 命令本身的状态,而不是仅在 bash shell 上有一个句柄而无法分辨 git(或它下面的其他子进程)是什么做。
  • @CharlesDuffy 这是你在 bash 中管道命令的方式
  • Popen(['/path/to/bash.exe', '-c', 'command; command; command']
  • 是的,这就是您在 bash 中设置管道的方式,但是您不会通过将 shell 的输出通过管道传输到该命令来在 shell 中运行命令。 bash | git clone 获取bash 的输出并将其作为git clone 的输入发送,但git clone 不会从标准输入中读取,bash 只会在该用法中等待输入,这就是您得到你在这里抱怨的行为('wait()' 永远不会退出)。

标签: python windows bash subprocess popen


【解决方案1】:

尝试Popen.terminate() 这可能有助于终止您的进程。如果您只有同步执行命令,请尝试直接与subprocess.call() 一起使用。

例如

import subprocess
subprocess.call(["c:\\program files (x86)\\git\\bin\\git.exe",
                     "clone",
                     "repository",
                     "c:\\repository"])
0

以下是使用管道的示例,但对于大多数用例而言,这有点过于复杂,并且只有在您与需要交互的服务进行对话时才有意义(至少在我看来)。

p = subprocess.Popen(["c:\\program files (x86)\\git\\bin\\git.exe", 
                      "clone",
                      "repository",
                      "c:\\repository"],
                      stdout=subprocess.PIPE,
                      stderr=subprocess.PIPE
                     )
print p.stderr.read()
fatal: destination path 'c:\repository' already exists and is not an empty directory.
print p.wait(
128

这也可以应用于 ssh

【讨论】:

  • p.terminate() 会有所帮助,是的,但是鉴于此处显示的用法,人们还可以解决 为什么 命令总是挂起。相比之下,subprocess.call() 将在 p.wait() 挂起时始终挂起。
【解决方案2】:

要杀死进程树,你可以use taskkill command on Windows:

Popen("TASKKILL /F /PID {pid} /T".format(pid=p.pid))

作为@Charles Duffy said,你的bash用法不正确。

要使用 bash 运行命令,请使用 -c 参数:

p = Popen([r'c:\path\to\bash.exe', '-c', 'git clone repo'])

在简单的情况下,您可以使用subprocess.check_call 而不是Popen().wait()

import subprocess

subprocess.check_call([r'c:\path\to\bash.exe', '-c', 'git clone repo'])

如果bash 进程返回非零状态(表示错误),后一个命令会引发异常。

【讨论】:

    猜你喜欢
    • 2011-09-16
    • 2011-09-07
    • 1970-01-01
    • 1970-01-01
    • 2011-02-21
    • 1970-01-01
    • 2014-06-02
    • 1970-01-01
    相关资源
    最近更新 更多