Почему подпроцесс продолжает работать после завершения общаться ()? - PullRequest
0 голосов
/ 21 октября 2019

У меня есть старый скрипт на python 2.7.5, который неожиданно создает проблемы в Red Hat Enterprise Linux Server версии 7.6 (Maipo). В конце концов, я вижу, что он отлично работает на Red Hat Enterprise Linux Server версии 7.4 (Maipo). Сценарий в основном реализует что-то вроде

cat /proc/cpuinfo | grep -m 1 -i 'cpu MHz'

путем создания двух подпроцессов и передачи вывода первого во второй (см. Пример кода ниже). В более новой версии ОС процессы cat остаются открытыми до тех пор, пока скрипт не завершится.

Кажется, что канал к grep каким-то образом удерживает процесс cat открытым, и я не могу найти никакой документации о том, как явно закрытьit.

Проблему можно воспроизвести, вставив этот код в CLI Python, а затем проверив список процессов ps на наличие статического процесса cat / proc / cpuinfo. Код разбивает то, что изначально происходит внутри цикла, поэтому, пожалуйста, не спорьте о его стиле. ; -)

import shlex
from subprocess import *
cmd1 = "cat /proc/cpuinfo"
cmd2 = "grep -m 1 -i 'cpu MHz'"
args1 = shlex.split(cmd1) # split into args
args2 = shlex.split(cmd2) # split into args
# first process uses default stdin
ps1 = Popen(args1, stdout=PIPE)
# then use the output of the previous process as stdin
ps2 = Popen(args2, stdin=ps1.stdout, stdout=PIPE)
out, err = ps2.communicate()
print(out)

После этого проверьте список процессов во втором сеансе (!) С помощью:

ps -eF |grep -v grep|grep /proc/cpuinfo

В RHEL7.4 я не обнаружил открытого процессав списке процессов, тогда как в RHEL 7.6 после некоторых попыток это выглядит следующим образом:

[reinski@myhost ~]$ ps -eF |grep -v grep|grep /proc/cpuinfo
reinski    2422  89459  0 26993   356 142 18:46 pts/3    00:00:00 cat /proc/cpuinfo
reinski    2597 139605  0 26993   352  31 18:39 pts/3    00:00:00 cat /proc/cpuinfo
reinski    7809 139605  0 26993   352  86 18:03 pts/3    00:00:00 cat /proc/cpuinfo

Эти процессы исчезнут только после закрытия CLI Python, и в этом случае я получаю такие ошибки (я оставилформатирование испорчено, как было):

cat: write error: Broken pipe
cat: write errorcat: write error: Broken pipe
: Broken pipe

Почему cat, очевидно, все еще хочет писать в канал, даже если он должен был уже вывести весь файл / proc / cpuinfo и должен был завершиться сам?

Или более важно: как я могу предотвратить это?

Спасибо за любую помощь!

Пример 2:

Учитывая предложение VPfB, оноОказалось, что мой пример был немного неудачным, поскольку ожидаемый результат может быть достигнут с помощью одной команды grep. Итак, вот модифицированный пример, чтобы показать проблему с конвейером по-другому:

import shlex
from subprocess import *
cmd1 = "grep -m 1 -i 'cpu MHz' /proc/cpuinfo"
cmd2 = "awk '{print $4}'"
args1 = shlex.split(cmd1) # split into args
args2 = shlex.split(cmd2) # split into args
# first process uses default stdin
ps1 = Popen(args1, stdout=PIPE)
# then use the output of the previous process as stdin
ps2 = Popen(args2, stdin=ps1.stdout, stdout=PIPE)
out, err = ps2.communicate()
print(out)

На этот раз результатом является один процесс-зомби для процесса grep (169731 - pid сеанса python):

[reinski@myhost ~]$ ps -eF|grep 169731
reinski  169731 189499  0 37847  6024 198 17:51 pts/2    00:00:00 python
reinski  193999 169731  0     0     0 142 17:53 pts/2    00:00:00 [grep] <defunct>

Итак, это просто еще один признак той же проблемы, или я здесь что-то не так делаю?

...