Проверить, не оставил ли процесс сирот.

Альтернативный подход к перенаправлению вывода вашего терминала на терминал другого пользователя:

Выполнение на вашем терминале:

mkfifo foo; script -f foo

Используйте команду who, чтобы увидеть терминал другого пользователя; а на другом вашем терминале перенаправьте вывод на терминал другого пользователя с правами root:

cat foo >> /dev/pts/2
2
16.05.2016, 11:31
2 ответа

Когда процесс завершается, PPID его дочерних процессов устанавливается в 1 (принятие init), но PGID (идентификатор группы процессов) и SID (идентификатор сессии) не изменяются.

Дочерние процессы, вероятно, не меняют свою группу процессов, если только они не предназначены быть демонами. Если это не так, запустите тестируемый процесс в его собственной группе процессов. Вызовите setpgid(getpid(), getpid()) из вашего тестового фреймворка, после форка и перед вызовом execve для выполнения тестируемой программы. Вызовите kill(-test_program_pid, 0) (kill с отрицательным аргументом pid и значением сигнала 0), чтобы проверить, существует ли запущенный процесс с PGID test_program_pid. Передайте SIGKILL в качестве аргумента сигнала, чтобы убить их всех.

test_program_pid = fork();
if (test_program_pid) {
    waitpid(test_program_pid, &status, 0);
    if (kill(-test_program_pid, 0)) {
        record_failue("some child processes were not terminated properly");
    }
    kill(-test_program_pid, SIGKILL);
} else {
    setpgid(getpid(), getpid());
    execve("/program/to/test", …);
}

Альтернативным методом может быть создание временного файла и открытие его в программе, которую вы тестируете, и нигде больше. Если программа вызывает execve, убедитесь, что дескриптор файла открыт без флага O_CLOEXEC (или вызовите fcntl(fd, FD_CLOEXEC, 0)). Этот метод предполагает, что программа не идет и не закрывает файловые дескрипторы, которые она явно не использует. Затем вы можете выполнить fuser /temp/file, чтобы перечислить процессы, у которых открыт этот файл, и fuser -k /temp/file, чтобы убить их. Вариант этого подхода, который работает даже с программами, закрывающими неиспользуемые дескрипторы файлов, но предполагает, что программа не меняет свой текущий каталог, заключается в создании временного каталога и переходе в этот каталог для запуска программы.

3
27.01.2020, 21:54

Один из способов найти их - использовать ps -ef , ища строки, в которых родительский идентификатор равен "1", например,

#!/bin/sh
orphans="$(ps -ef | awk '$3 == 1{ print $2; }')"
echo "Processes which might be orphans: $orphans"

Однако многие процессы имеют «1» в качестве родительского. Определить, какие из них вам интересны, лучше всего можно сделать, вспомнив, какие дочерние процессы были созданы вашей программой.

Если вам известно имя пользователя (и / или идентификатор пользователя ), под которым создаются эти процессы, вы можете исключить некоторые возможности. В первом столбце ps может отображаться (в зависимости от типа системы) либо имя пользователя , либо соответствующий идентификатор пользователя . POSIX предлагает некоторую помощь здесь, но легко найти системы, которые отличаются - и документация отражает это:

  • FreeBSD 10, например, не показывает имя входа для Опция -f . С помощью всего лишь ps -ef он показывает идентификатор процесса в первом столбце и не показывает идентификатор родительского процесса. Требуется опция -l для отображения (вместо этого) идентификатора пользователя .
  • OSX предоставляет идентификатор пользователя в любом случае ( ps -ef или ps -efl ).
  • С учетом параметра -l Solaris 10 показывает флаги процесса в первом и втором столбцах. Это упоминается в POSIX, хотя содержимое флагов не определено (поскольку содержимое различается на платформах Unix ).
  • Linux предоставляет логин и флаги процесса согласно POSIX.

Как видите, для некоторого подмножества доступных систем ps -efl даст «одинаковый» результат для первых трех столбцов. Для чего-то более общего вам нужно будет посмотреть на заголовок (первая строка) и определить, какой столбец содержит информацию, соответствующую владельцу процесса ( имя пользователя или идентификатор пользователя ). и идентификатор процесса и его родительский идентификатор процесса.

Для данной системы (зная используемые параметры для ps и зная, следует ли сопоставить имя входа или идентификатор пользователя ), вы можете использовать awk для соответствия , что и поле , например,

#!/bin/sh
orphans="$(ps -ef | awk -v user=$LOGNAME '($1 == user && $3 == 1){ print $2; }')"
echo "Processes which might be orphans: $orphans"

Здесь я использовал $ LOGNAME , чтобы учесть использование POSIX термина имя пользователя , что может вводить в заблуждение (поскольку в принципе процессы могут осуществляться через sudo , в то время как использование этого термина в POSIX подразумевает, что они пришли через «логин»).

Дополнительная литература:

4
27.01.2020, 21:54

Теги

Похожие вопросы