Как завершить процесс, запущенный в родительском терминале и в «n» дочерних терминалах в linux, используя python? - PullRequest
1 голос
/ 02 апреля 2020

Я запускаю python скрипт "./main.py" в терминале Linux, который автоматически запускает два других терминала и запускает в нем два разных кода, я делаю это следующим образом,

import os
import sys
import subprocess
import rospy
import psutil, sys
import signal

print(os.getpid())
arra = []
arra.append(os.getpid())
for i in range(2):
    if i == 0:     
        p = subprocess.Popen(['gnome-terminal', '--', 'roslaunch', 'ur5_notebook', 'main_r2_mt.launch', 'gui:=False'])
    if i > 0:
        p = subprocess.Popen(['gnome-terminal', '--', 'roslaunch', 'ur5_notebook', 'main_r2_mt.launch'])

    arra.append(p.pid)

rospy.sleep(20)

Теперь я также хочу уничтожить родительский терминал, а также весь дочерний терминал, который я запустил. Сначала я сделал снимок с помощью sys.exit (), т.е.

print(os.getpid())
arra = []
arra.append(os.getpid())
for i in range(2):
    if i == 0:     
        p = subprocess.Popen(['gnome-terminal', '--', 'roslaunch', 'ur5_notebook', 'main_r2_mt.launch', 'gui:=False'], preexec_fn=os.setpgrp)
    if i > 0:
        p = subprocess.Popen(['gnome-terminal', '--', 'roslaunch', 'ur5_notebook', 'main_r2_mt.launch'], preexec_fn=os.setpgrp)
# rospy.sleep(50)
    arra.append(p.pid)
# print(list(os.getgroups))
rospy.sleep(20)

sys.exit()

Но это убило только текущий / родительский терминал, дочерние терминалы все еще были активны

Затем я попытался убить отдельного идентификатор процесса (PID), который я делаю следующим образом:

import os
import sys
import subprocess
import rospy
import psutil, sys
import signal

print(os.getpid())
arra = []
arra.append(os.getpid())
for i in range(2):
    if i == 0:     
        p = subprocess.Popen(['gnome-terminal', '--', 'roslaunch', 'ur5_notebook', 'main_r2_mt.launch', 'gui:=False'])
    if i > 0:
        p = subprocess.Popen(['gnome-terminal', '--', 'roslaunch', 'ur5_notebook', 'main_r2_mt.launch'])

    arra.append(p.pid)

rospy.sleep(20)

for i in reversed(arra):
     print(i)
     os.killpg(i, signal.SIGINT)

Но, тем не менее, закрывается только текущий процесс терминала, а не дочерний процесс. Пожалуйста, дайте мне понять, где я мог ошибиться. Я хочу написать скрипт, который закрывает все терминалы, связанные с родительским терминалом.

1 Ответ

0 голосов
/ 03 апреля 2020

У вас возникли проблемы с использованием вашего кода, поскольку gnome-terminal отправляет запрос на gnome-terminal-server, чтобы запустить новый терминал, а затем завершает работу. Вы можете проверить это самостоятельно, выполнив следующий код (небольшое изменение вашего кода), где gnome-terminal вызывается в одном процессе, а xterm вызывается в другом:

import os
import sys
import subprocess
import psutil, sys
import signal
import time

print(os.getpid())

arra = []
#arra.append(os.getpid())

for i in range(2):
    if i == 0:     
        p = subprocess.Popen(['gnome-terminal', '--', 'yes'])
        print ("gt: " + str(p.pid))
    if i > 0:
        p = subprocess.Popen(['xterm', '-hold', 'yes'])
        print("xt: " + str(p.pid))
    arra.append(p.pid)

for i in reversed(arra):
    print("next kill:" + str(i))
    time.sleep(60)
    os.kill(i, signal.SIGTERM)

Если вы вызываете ps -e | grep gnome-terminal в другой оболочке во время выполнения приведенного выше кода, вы увидите, что gnome-terminal больше не существует, и поэтому вы не можете его убить. С другой стороны, если вы используете, например, xterm, все работает так, как вы ожидали.

Пример вывода:

gt: 26054
xt: 26055
next kill:26055

-----------------------------

$ ps -e | grep gnome-terminal
26054 pts/2    00:00:00 gnome-terminal <defunct>

Поэтому можно использовать xterm для выполнения вашего кода или другой тип терминала с аналогичным поведением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...