Уничтожение sudo-запущенного подпроцесса в python - PullRequest
0 голосов
/ 31 мая 2018

Я работаю с пользователем, который может выполнять вызовы уровня root без необходимости ввода пароля.Мой пользователь в настоящее время делает что-то подобное

pr = subprocess.Popen("sudo sleep 100".split())
sleep(5)
pr.kill()

, но это приводит к этой ошибке, потому что пользователь не является пользователем root, поэтому он не может уничтожить корневой процесс

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/subprocess.py", line 1572, in kill
    self.send_signal(signal.SIGKILL)
  File "/usr/lib/python2.7/subprocess.py", line 1562, in send_signal
    os.kill(self.pid, sig)
OSError: [Errno 1] Operation not permitted

, поэтому я пытаюсьсделать что-то вроде этого

pr = subprocess.Popen("sudo sleep 100".split())
sleep(5)
kill_pr = subprocess.Popen("sudo kill {}".format(pr.pid))

, но это не убивает рассматриваемый процесс.Например, если

>> subprocess.Popen("sudo sleep 100".split()).pid
5000

, но

$ pgrep sleep
5001

, то кажется, что pid, возвращаемый из subprocess.Popen("..").pid, на единицу выше, чем фактический pid процесса, выполняющего команду, котораяЯ хочу убить

Я предполагаю, что pid, возвращенный из вызова Popen, является родительским процессом, поэтому я пытаюсь сделать что-то вроде

sudo kill -- -$PID, где $PID тот, который возвращается из Popen, но это просто дает мне

kill: sending signal to -2100 failed: No such process

почему процесс не существует?

По сути, мне просто нужен способ запустить команду сsudo с помощью подпроцесса python, а затем смогу убить его, когда мне нужно.Я предполагаю, что мне нужно выполнить какой-то тип sudo kill команды с pid процесса, который я пытаюсь убить, или что-то в этом роде, но я не могу точно определить, как это сделать.

Ответы [ 2 ]

0 голосов
/ 31 мая 2018

Я думаю, я понял это, проблема заключалась в том, что если бы я сделал это

import subprocess, os
pr = subprocess.Popen(["sudo", "sleep", "100"])
print("Process spawned with PID: %s" % pr.pid)
pgid = os.getpgid(pr.pid)
subprocess.check_output("sudo kill {}".format(pgid))

, это убило бы процесс, который запустил интерпретатор python

>>> Terminated

, поэтому вместо этого яустановите preexec_fn в os.setpgrp

import subprocess, os
pr = subprocess.Popen(["sudo", "sleep", "100"], preexec_fn=os.setpgrp)
print("Process spawned with PID: %s" % pr.pid)
pgid = os.getpgid(pr.pid)
subprocess.check_output("sudo kill {}".format(pgid))

в другой оболочке, если я проверю,

pgrep sleep

ничего не появляется, поэтому он фактически убит.

0 голосов
/ 31 мая 2018

Когда вы выполните pgrep sleep, вам будет показан PID команды sleep, работающей как дочерний элемент процесса sudo, который вы создали.

В качестве быстрой демонстрации я сохранил следующее какsubproc.py:

import subprocess
pr = subprocess.Popen(["sudo", "sleep", "100"])
print("Process spawned with PID: %s" % pr.pid)

При запуске этого скрипта мы видим два процесса:

~/$ python subproc.py
Process spawned with PID: 5296

~/$ ps all | grep sleep
    0  5296     1     sudo sleep 100
    0  5297  5296     sleep 100

Вы заметите, что PID, о котором вы знаете в своем коде, является 'родительский процесс sudo.Это процесс, который вы должны убить, но для этого вам понадобится sudo:

subprocess.check_call(["sudo", "kill", str(pr.pid)])
#You might want to wait for the process to end:
os.waitpid(pr.pid, 0)
...