Мне нужно запускать практически произвольные команды в (удаленной) оболочке в эфемерных контейнерах/виртуальных машинах для механизма выполнения тестов. Иногда эти фоновые процессы приводят к утечке, что приводит к зависанию всей команды. Это можно свести к этой простой команде:
$ sh -c 'sleep 30 & echo payload'
payload
$
Здесь фоновый sleep 30
играет роль просочившегося процесса (который на самом деле будет чем-то вроде dbus-daemon
), а эхо — это то, что я хочу запустить. sleep 30 & echo payload
здесь следует рассматривать как пример атомарной непрозрачной команды.
Вышеупомянутая команда в порядке и возвращает немедленно, так как stdout/stderr оболочки, а также спящий режим являются PTY. Однако при захвате вывода команды в канал/файл (в конце концов, тестировщик хочет сохранить все в журнал), вся команда зависает:
$ sh -c 'sleep 30 & echo payload' | cat
payload
# ... does not return to the shell (until the sleep finishes)
Теперь это можно исправить с помощью довольно смехотворно сложной магии оболочки, которая определяет FD stdout/err из /proc/$$/fd/{1,2}
, перебирает ls /proc/[0-9]*/fd/*
и убивает каждый процесс, который также имеет такой же stdout/stderr. Но это включает в себя много хрупкого кода оболочки и дорогостоящих сравнений строк оболочки.
Есть ли способ очистить эти просочившиеся фоновые процессы более элегантным и простым способом? setsid
не помогает:
$ sh -c 'setsid -w sh -c "sleep 30 & echo payload"' | cat
payload
# hangs...
Обратите внимание, что группы/сеансы процессов и полное их уничтожение недостаточно, поскольку просочившиеся процессы (такие как dbus-daemon) часто сами устанавливают id.
P.S. В этих средах я могу предположить только оболочку POSIX или bash; нет Python, Perl и т.д.
Заранее спасибо!
sh -c '{ sleep 30 | cat ; } & { echo payload | cat ; }'
- person serge-sans-paille   schedule 02.09.2015$ setsid -w sh -c 'sleep 30 & echo payload; RC=$?; for p in $(pgrep --pgroup 0); do [ $p = $$ ] || kill $p; done; exit $RC' | cat
Простое использованиеkill -- -$$
слишком агрессивно, так как оно также убивает саму оболочку. - person Martin Pitt   schedule 02.09.2015sh -c '(sleep 30 & echo payload|cat)'
- person cdarke   schedule 02.09.2015sh -c '(sleep 30 & echo payload)'|cat
. - person Martin Pitt   schedule 02.09.2015disown -a
?sh -c '(sleep 30 & echo payload);disown -a|cat'
(обратите внимание на позицию в конце кавычки) - person cdarke   schedule 02.09.2015