запуск новой группы процессов из сценария bash

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

Я обнаружил, что в Linux мне в этом помогает setsid, но во FreeBSD это недоступно.

Синтаксис для setsid (предоставляется util-linux-ng).

setsid /path/to/myscript

Однако я узнал, что сеанс и группа процессов - это не одно и то же. Но запуск нового сеанса также решает мою проблему.


person Thirupathi Thangavel    schedule 10.06.2015    source источник
comment
Если вы можете скомпилировать код C, исходный код программы setsid для FreeBSD находится по адресу lists.freebsd.org/pipermail/freebsd-hackers/2011-February/ .   -  person Mark Plotnick    schedule 16.06.2015


Ответы (3)


Сеансы и группы — это не одно и то же. Давайте сделаем вещи чистыми:

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

Кроме того, когда сеанс имеет управляющий терминал, процесс оболочки обычно является лидером сеанса, диктуя, какая группа процессов является группой процессов переднего плана (неявно делая другие группы группами фоновых процессов). Процессы в группе обычно помещаются туда линейным конвейером. Например, ls -l | grep a | sort обычно создает новую группу процессов, в которой живут ls, grep и sort.

Оболочки, поддерживающие управление заданиями (которое также требует поддержки со стороны ядра и драйвера терминала), как и в случае с bash, создают новую группу процессов для каждой вызываемой команды, и если вы вызываете ее для выполнения в фоновом режиме (с &), эта группа процессов не получает контроль над терминалом, и оболочка делает ее фоновой группой процессов (а группа процессов переднего плана остается оболочкой).

Итак, как видите, в этом случае вы почти наверняка не захотите создавать сеанс. Типичная ситуация, когда вы хотите создать сеанс, — это демонизация процесса, но кроме этого, создание нового сеанса обычно не имеет особого смысла.

Вы можете запустить скрипт как фоновое задание, как я уже упоминал, это создаст новую группу процессов. Поскольку fork() наследует идентификатор группы процессов, каждый процесс, выполняемый сценарием, будет находиться в одной группе. Например, рассмотрим этот простой скрипт:

#!/bin/bash

ps -o pid,ppid,pgid,comm | grep ".*"

Это печатает что-то вроде:

  PID  PPID  PGID COMMAND
11888 11885 11888 bash
12343 11888 12343 execute.sh
12344 12343 12343 ps
12345 12343 12343 grep

Как видите, execute.sh, ps и grep находятся в одной группе процессов (значение в PGID).

Итак, все, что вы хотите, это:

/path/to/myscript &

Затем вы можете проверить идентификатор группы процессов myscript с помощью ps -o pid,ppid,pgid,comm | grep myscript. Чтобы отправить сигнал группе, отправьте его лидеру группы (PGID — это PID лидера группы). Сигнал, отправленный группе, доставляется каждому процессу в этой группе.

person Filipe Gonçalves    schedule 10.06.2015
comment
Я хочу вызвать свой скрипт (скажем, скрипт-1) из основного скрипта. И я хочу, чтобы этот скрипт запускался в новой группе процессов. Вызов script-1 в фоновом режиме не запускает его в новой группе процессов. - person Thirupathi Thangavel; 11.06.2015
comment
Выполнение команды в фоновом режиме поместит его в другую группу. Однако, если вы хотите запустить что-то, например. использует readbuiltin из bash, есть ли способ запустить такой скрипт в новой группе процессов? Причина, по которой я хотел бы иметь новую группу процессов, заключается в том, что SIGINT будет доставляться только этой группе в случае нажатия Ctrl+C. - person Mikko Rantalainen; 27.01.2021
comment
управление заданиями по умолчанию отключено в неинтерактивном режиме (stackoverflow.com/a/690297/18096) и только, кажется, когда управление заданиями включено, фоновые конвейеры получают свою собственную группу процессов - person Martin Dorey; 01.02.2021

Используя FreeBSD, вы можете попробовать использовать команду script, которая внутренне выполнит команду setsid.

stty -echo -onlcr   # avoid added \r in output
script -q /dev/null /path/to/myscript
stty echo onlcr
# sync  # ... if terminal prompt does not return
person taroj    schedule 11.03.2016

Это не совсем ответ, а альтернативный подход, основанный на именах.

У вас может быть общая часть имени для всех процессов. Например, у нас есть часть my_proc_group_29387172 для всех следующих процессов:

-rwxrwxr-x.   my_proc_group_29387172_microservice_1
-rwxrwxr-x.   my_proc_group_29387172_microservice_2
-rwxrwxr-x.   my_proc_group_29387172_data_dumper

Создайте их все (и столько, сколько хотите):

ADDR=1 ./my_proc_group_29387172_microservice_1
ADDR=2 ./my_proc_group_29387172_microservice_1
ADDR=3 ./my_proc_group_29387172_microservice_2
./my_proc_group_29387172_data_dumper

Если вы хотите убить все процессы, вы можете использовать команду pkill (шаблон kill) или killall с параметром --regexp:

pkill my_proc_group_29387172

Преимущество :) - вы можете запускать сколько угодно процессов в любое время (или в любой день) из любого скрипта.

Недостаток :( - вы можете убивать невинные процессы, если они имеют общую часть имени с вашим шаблоном.

person DenisKolodin    schedule 14.01.2019