Как установить группу процессов оболочки script

Как установить группу процессов оболочки script? Также я хочу, чтобы весь дочерний процесс находился в одной группе процессов

Я ожидаю нечто подобное setpgid() в C.

Ответ 1

Как указывает PSkocik, можно запустить процесс в своей собственной группе процессов в большинстве оболочек, активировав управление заданиями ( "режим монитора" ).

(set -m; exec process_in_its_own_group)

У Linux есть утилита setsid, которая запускает команду, переданную как аргумент, в свой собственный сеанс (используя одноименный системный вызов). Это сильнее, чем запустить его в своей собственной группе setpgrp, но это может быть хорошо для вашей цели.

Если вы хотите поместить процесс в существующую группу, а не в свою собственную группу (т.е. если вы хотите использовать полную мощность setpgid), нет общей утилиты оболочки. Вы должны использовать C/Perl/...

Ответ 2

Я не думаю, что Bourne, bash или zsh позволят вам это сделать, но вы можете сделать это в perl, используя встроенный setpgrp (обратите внимание на небольшое различие имен от POSIX). Передайте ноль в качестве PID, чтобы изменить группу самого процесса perl:

setpgrp(0, 12345) || die "$!"

Возможно, вы могли бы использовать perl, например, bash, чтобы установить группу процессов bash (например, передав $$ в perl script), но я не думаю, что perl процесс мог бы изменить группу процесса, в котором он не был вилок.

В зависимости от того, что вы пытаетесь сделать, функции управления заданиями в разных оболочках могут дать вам то, что вам нужно, по-другому, например, если вы просто хотите отсоединиться от терминала.

ОБНОВЛЕНИЕ: Мне кажется странным, что этот ответ получил пару голосов без объяснения причин. Я предполагаю, что downvoters неправильно понимают вопрос, который спрашивает, как изменить группу процессов текущей оболочки. Или, может быть, они знают, как делать setpgrp из оболочки, но сохраняют в себе секрет.

Ответ 3

Я отвечу на часть того, что понимаю:

Как принудительно использовать текущую оболочку bash script как самостоятельную группу процессов:

Я положил это в начале моего bash script:

pgid_from_pid() {
    local pid=$1
    ps -o pgid= "$pid" 2>/dev/null | egrep -o "[0-9]+"
}

pid="$$"
if [ "$pid" != "$(pgid_from_pid $pid)" ]; then
    exec setsid "$(readlink -f "$0")" "[email protected]"
fi

Зачем мне это нужно?

При запуске программы из интерактивного сеанса bash он получает свою собственную новую группу процессов. Но это не так, если ваша программа вызывается из bash script (не интерактивная). Если ваша программа зависит от владельца группы процессов в обоих условиях, вам понадобится это.

Ответ 4

Если вы включите set -m, новые процессы будут созданы в новой группе процессов, и если они будут созданы, они не будут игнорировать SIGINT и SIGQUIT.

if  [ $$ = $(ps -o pgid -hp $$) ]; then
   echo already a process group leader;
else
   set -m
   $0 "[email protected]" #optionally with &
   set +m
fi

Новая группа процессов программ, запускаемых после set -m, берет на себя роль группы процессов переднего плана терминала, если они не выполняются в фоновом режиме.

set -m, по-видимому, является полустандартным, требуемым POSIX, если реализация поддерживает "Утилиты пользовательской переносимости". На практике он работает на bash, dash, ksh, pdksh, sh, yash и zsh. posh не имеет его.

Ответ 5

Как @Rob Davis указал в его ответе, настройка группы процессов не является тем, что вы хотите для оболочек.

Вместо этого вы хотите использовать свои механизмы управления процессом. Этот ответ охватывает выполнение этого для sh на linux и переносится. Короче говоря:

#! /bin/sh
# Kill all opened jobs on exit.
trap 'kill $(jobs -p)' EXIT

Это приведет к уничтожению любых заданий, открытых на обратной стороне (например, с помощью &).