终止使用子进程打开的gnome终端

时间:2016-01-07 15:49:27

标签: python terminal subprocess

使用子流程和命令' gnome-terminal -e bash'我可以根据需要打开一个gnome-terminal(并让它坚持下去)。这可以通过

完成
p=subprocess.Popen(['gnome-terminal', '-e', 'bash'])

p=subprocess.Popen(['gnome-terminal -e bash'], shell=True)

但我无法使用p.terminate()p.kill()关闭终端。根据我的理解,使用shell=True时这有点棘手,但我不希望遇到问题。

2 个答案:

答案 0 :(得分:2)

终止终端及其子终端(在同一进程组中):

#!/usr/bin/env python
import os
import signal
import subprocess

p = subprocess.Popen(['gnome-terminal', '--disable-factory', '-e', 'bash'],
                     preexec_fn=os.setpgrp)
# do something here...
os.killpg(p.pid, signal.SIGINT)
  • --disable-factory用于避免重新使用活动终端,以便我们可以通过subprocess句柄
  • 杀死新创建的终端
  • os.setpgrpgnome-terminal放入其自己的流程组中,以便os.killpg()可用于向此群组发送信号

答案 1 :(得分:1)

您应该能够解决这个问题:

  • 获取流程ID
  • 杀死进程

工作解决方案:关闭gnome-terminal-server

正如@ j-f-sebastian在评论中所建议的那样,gnome-terminal

  

只是发送请求(到gnome-terminal-server)以启动一个新的终端并立即退出 - 没有什么可以杀死进程已经死了(新创建的进程不是后代:新的{{1} } process是bash的孩子,而不是gnome-terminal-server)。

gnome-terminal

我的解决方案遵循以下逻辑:

  • 运行gnome-terminal
  • 获取最新的bash实例打开进程ID
  • 杀死此进程ID

破碎的解决方案

这些解决方案可能适用于更简单的情况:

解决方案1 ​​

import subprocess
import os, signal
import time

p=subprocess.Popen(['gnome-terminal -e bash'], stdout=subprocess.PIPE, shell=True, preexec_fn=os.setsid)
print "this is going to be closed in 3 sec"
time.sleep(3)
# this line returns the list of bash instances pid as string
bash_pids = subprocess.check_output(["pidof", "bash"])
# I get the last instance opened
pid_to_kill = bash_pids.split(" ")[0]
os.kill(int(pid_to_kill), signal.SIGTERM)

为了选择合适的信号传递方法而不是 SIGKILL ,您可以参考signal documentation。 E.g。

  

在Windows上,只能使用SIGABRT,SIGFPE,SIGILL,SIGINT,SIGSEGV或SIGTERM调用signal()

对于Unix,你有一个非常广泛的方法列表来调用。

要更好地了解 os.kill ,您可以参考its documentation

解决方案2

对Unix有用的另一种方法可能是:

import subprocess
import os, signal

p=subprocess.Popen(['gnome-terminal -e bash'], shell=True)
p_pid = p.pid  # get the process id
os.kill(p_pid, signal.SIGKILL)

您的流程似乎正在打开子进程,阻止父进程关闭。将session id添加到父进程,您应该能够修复它。

解决方案3

import subprocess
import os, signal

p=subprocess.Popen(['gnome-terminal -e bash'], stdout=subprocess.PIPE, shell=True, preexec_fn=os.setsid)
os.killpg(os.getpgid(p.pid), signal.SIGTERM)

此解决方案需要psutil

解决方案4

根据askubuntu,似乎关闭gnome终端实例的最佳方法是执行bash命令,如:

import subprocess, psutil

def kill(p_pid):
    process = psutil.Process(p_pid)
    for proc in process.get_children(recursive=True):
        proc.kill()
    process.kill()

p = subprocess.Popen(['gnome-terminal -e bash'], shell=True)
try:
    p.wait(timeout=3)
except subprocess.TimeoutExpired:
    kill(p.pid)

其中{signal}模拟Alt + F4。

您可以尝试使用[ pexpect ]:

killall -s {signal} gnome-terminal