Завершение дочерних процессов 2 уровня, Аноним, 13-Май-20, 01:56 [смотреть все]Подскажите, как лучше его организовать? Ситуация следующая: дети запускаются фоном, после чего они рождают ещё детей. Мне нужно всех их вырезать, потому что, если их не прибить собственноручно, они остаются жить навсегда. Добился нужного через pkill -g $$ в конце (повесил на выход), но возникают определённые подозрения (в частности в связи с тем, что при самоубийстве в баше не появляется приглашение, видимо фишка баша для провисших дескрипторов) или же вообще ломается любой ввод (он не отображается). Я так понял, это вообще проблема, в линуксе нельзя просто взять и узнать, кого мы родили. Мне только pstree -p $bgjobpid показывает, что там кто-то где-то висит во внучках (он обходит всех на предмет родителей?), разбирать выхлоп pstree чёт видится извратом. Вообще, в интернете обещали и что pkill -P $$ будет достаточно, да только дети детей то остаются!Суть дела: мне нужно убить всех детей вместе с их детьми средствами, доступными родителю, в идеале получить перечень пидов и их перебить. Я могу получить пид мейна, скажем, через ppid/pgrp/tpgid, или даже того, кто запускал (баш) из sid, но я не могу получить перечень порождённых процессов и желательно перебить их всех по цепочке? Если не останавливать фоновый процесс через прямое убийство (что я делал изначально, поскольку я прекрасно вижу его в мейне), он вместе со всеми порождёнными (уже не видимыми мне) им переходит под инит при завершении. Если останавливать, порождённые им процессы остаются висеть (под инитом). Пробовал уже по-всякому, и kill, и pkill, и всё остальное, но внучки остаются недосягаемыми. Из информации, полученной со стаковерфлоу, я сделал вывод, что единственный выход тут, это использовать неймспейс (и грохать его). Так ли это? Как же живут пользователи других систем? И я смотрю unshare с --kill-child=sigkill как-то странно реагирует на ^C -- я так понимаю ему прилетает kill и sigint не доходит до приложения, в следствии чего я не могу обработать этот кейс в коде -- всё слишком быстро умирает. Или даже не так, но умирает всё равно раньше, чем я успеваю почистить файлы в перехватчике int. А с другими сигналами kill-child (term,int), всё умирает, но приглашение не появляется. Т.е. неймспейсы тут не подходят. Это конечно хорошо, что мой код работает, но плохо, что я его не понимаю. Чем мне грозит pkill -g $$ на практике? Видимых проблем я не вижу, всё в полном порядке, вот только провисшие дескрипторы меня пугают.
|
- Завершение дочерних процессов, Аноним, 03:02 , 13-Май-20 (1)
Что-то не то с порядком исполнения, или же временем? Если на exit повешено несколько действий, прилетает sigterm. Если там один pkill -g $$, всё нормально завершается. повесил новую ловушку на выход в ловушке на выход. Что-то странное, я всё чаще начинаю замечать, что не понимаю, почему мой баш работает и как он это делает.
- Завершение дочерних процессов, Аноним, 07:19 , 13-Май-20 (2) +1
Да тебе бы сценарии к триллерам писать, а не вот это вот всё) ))
- Завершение дочерних процессов, eRIC, 13:32 , 13-Май-20 (3) +1
предлагаю название темы поменять, потому-что по таким словам как: "убийство внучек", "суицид" ресурс OpenNet не забанили
- Завершение дочерних процессов 2 уровня, Аноним, 14:39 , 13-Май-20 (4)
> Ситуация следующая: дети запускаются фоном, после чего они рождают ещё детей.Породив внуков, дети завершаются или остаются жить? Тут нужно либо обучить детей передавать прилетающие SIGTERM'ы и SIGINT'ы внукам (см. встроенные в bash команды trap и jobs), либо как-то передавать список внуков родителю. > что единственный выход тут, это использовать неймспейс (и грохать его). В Linux ещё control groups, и они, как мне представляется, более подходят к данному случаю.
- Завершение дочерних процессов 2 уровня, Аноним, 17:22 , 13-Май-20 (5)
Они живут пока мамка жива, если мейн сворачивается по любой из причин внучки должны быть завершены сразу после детей (чтобы детям от них данные не попали и не было гонки). С внучками ещё проблема в том, что они даже не баш и не могут реагировать на изменения предка.Я попробовал навесить трапов на фоновый жоб, так я всё равно не могу узнать кого мы родили и там! И начинается вообще какая-то дичь, которую я не могу контролировать (сейчас хотя бы порядок срабатывания обработчиков не нарушается, всё разруливается в мейне имеющем все необходимые данные). У меня нет доступа в детях к внучкам, потому что дети ждут пока внуки завершатся или умрут (это даже не важно, что из двух) и это событие тригеррит детей, которые после этого обрабатывают полученные данные и взаимодействуют с мейном (через файл на диске, угу). Я так понимаю для работы с cgroups мне понадобится модификация системы и суидные рутовые бинарники? Потому что неймспейсы могут быть пользовательскими (чем весь софт вроде браузеров пользуется и суидные песочницы это вроде как уже не модно), а cgroups от пользователя можно как-то управлять исключительно через systemd,
- Завершение дочерних процессов 2 уровня, Аноним, 20:38 , 13-Май-20 (6)
> У меня нет доступа в детях к внучкам, потому что дети ждут пока внуки завершатся или умрутДети — bash? Внуков можно запускать в фоновом режиме (команда &), тогда доступ к ним остаётся. Также можно ждать завершения фоновых процессов встроенной командой wait. Bash, кстати, при получении SIGTERM'а автоматически передаёт его всем фоновым потомкам. > Я попробовал навесить трапов на фоновый жоб, так я всё равно не могу узнать кого мы родили и там! jobs выдаёт список фоновых процессов, не? > Я так понимаю для работы с cgroups мне понадобится модификация системы и суидные рутовые бинарники? Достаточно systemd-run или пользовательской сессии systemd. Возможно, эту всю скриптоту удобнее писать не на bash'е, а на юнитах systemd.
- Завершение дочерних процессов 2 уровня, Аноним, 21:19 , 13-Май-20 (7)
Вот пример кода:EXBGFILE=$(mktemp -p /dev/shm/ --suffix=wdfile)sendvalue() { echo "${1}">${EXBGFILE} } readvalue() { echo "$(<${EXBGFILE})" } sendvalue 0 bgloop() { while sleep 9 & wait; do echo "exec" var=$(readvalue) echo "${FUNCNAME} read:${var}" done } bgloop & bgjob=$! trap "kill '$bgjob'; rm -v -- '${EXBGFILE}'" EXIT echo `jobs -l` echo `jobs -p` sendvalue 2 sleep 10 sendvalue 5 sleep 10 sendvalue 9 sleep 10 sendvalue 11 echo done
Если я посылаю ^C скрипту, sleep 9 переходит под инит до завершения (kill останавливает только фоновый жоб и sleep никак не остановить). Сейчас я вешаю такую конструкцию на завершение мейна, чтобы убить себя, и при этом прилетало и внучке. У меня есть ощущение, что лучше обойтись без самоубийства (остановки группы процессов, к которой принадлежат все порождённые процессы включая мейн). trap "kill '$bgjob'; rm -v -- ${EXBGFILE}; trap 'pkill -g $$' EXIT;" EXIT;
При этом kill '$bgjob' (как и jobs -p в мейне) вообще не надёжная тема, процесса может и не оказаться, если мы дёргаем sigint, и тогда килл жалуется, мол, но сач процесс. Однако, pkill -g $$ всегда завершает всех без эксцессов (при таком использовании -- если в trap exit что-то постороннее, прилетает terminated).
- Завершение дочерних процессов 2 уровня, Аноним, 21:24 , 13-Май-20 (8)
Ой я имел в виду у меня конечно sigint отдельно, всё равно после завершения остаются висеть под мейном. Я запустил этот пример, и у меня слипы плодятся несколько раз, но последний переходит под инит и висит до завершения и вот он-то мне и нужен исчезнувшим сразу.
- Завершение дочерних процессов 2 уровня, Аноним, 21:55 , 13-Май-20 (10)
Нужно сделать ещё один trap в bgloop():
#!/usr/bin/env bash trap 'kill %' EXITbgloop() { trap 'kill %' EXIT while sleep 10 & wait; do : done } bgloop & wait
Так при прибитии родителя прибиваются также все дети.
- Завершение дочерних процессов 2 уровня, Аноним, 22:25 , 13-Май-20 (11)
Похоже, то что нужно, спасибо. Только всё ещё не понятно, почему $bgjob и jobs -p сообщают о процессе, который не существует с точки зрения kill при sigint. Он исчезает из-за sigint? И как мне его останавливать тогда, если для мейна его уже нет из-за sigint? Он может и быть, а может и не быть. Неприятненько, куда лучше, когда код без плавающих багов.
- Завершение дочерних процессов 2 уровня, Аноним, 12:11 , 14-Май-20 (13)
> почему $bgjob и jobs -p сообщают о процессе, который не существует с точки зрения kill при sigint. > Он может и быть, а может и не быть..Сейчас проверил, своим потомкам, если это не внешние программы, bash пересылает сигналы завершения сам автоматически, т.е. в коде #10 первый trap излишен, а $bgjob из #7, видимо, был прибит до вызова kill. > Если отправлять pkill -g $$ в мейне, то bgloop получает только int (не term) и до обработчика exit дело не доходит. trap ... EXIT срабатывает и на INT (который также прилетает по ctrl+c), и на TERM. > смерть не мгновенная? Естественно: используемые сигналы можно перехватить и обработать. Нельзя обработать KILL, SEGV и некоторые другие.
- Завершение дочерних процессов 2 уровня, Аноним, 17:14 , 14-Май-20 (14)
> Сейчас проверил, своим потомкам, если это не внешние программы, bash пересылает сигналы > завершения сам автоматически, т.е. в коде #10 первый trap излишен, а > $bgjob из #7, видимо, был прибит до вызова kill.1 trap там не излишен, он вообще не работает -- bgloop переходит под инит и остаётся висеть. Он должен быть заменён на bgloop & trap "kill $!" EXIT
Тогда работает, но только если bgloop остановлен kill (sigterm) в мейне. Если bgloop прерывается sigint (что происходит не каждый раз) >> Если отправлять pkill -g $$ в мейне, то bgloop получает только int (не term) и до обработчика exit дело не доходит. > trap ... EXIT срабатывает и на INT (который также прилетает по ctrl+c), > и на TERM. срабатывает, только exit отдельно стрелял после int при нажатии ^C, теперь только на int. Я уже сталкивался с тем, что простые примеры ведут себя не так, как чуть более сложные (из-за разного времени реакции системы надо полагать) >> смерть не мгновенная? > Естественно: используемые сигналы можно перехватить и обработать. Нельзя обработать KILL, > SEGV и некоторые другие. Дело не в обработке, я опасаюсь, что возникнет гонка из-за задержки между отправкой сигнала и реакцией на него. В примере из #10 bgloop дети переходят под мейн и продолжают работать бесконечно . И мне не надо bgloop& wait, мне надо чтобы он работал параллельно, в #10 мы в мейне ждём завершения фонового процесса, которое не случится пока мы не прервём. Мейн должен работать и передавать данные в bgloop, я ведь не зря привёл такой пример в #7.
- Завершение дочерних процессов 2 уровня, Аноним, 20:25 , 14-Май-20 (15)
> И мне не надо bgloop& wait, мне надо чтобы он работал параллельно, в #10 мы в мейне ждём завершения фонового процесса, которое не случится пока мы не прервём.В #10 главный скрипт завершается до завершения bgloop'а, в этом проблема. Мэйн должен либо что-то делать, либо ждать завершения детей, но не завершаться сам. Можно запихнуть wait в конец, после кормёжки детей данными, это спасёт от состояния гонки.
- Завершение дочерних процессов 2 уровня, Аноним, 20:05 , 15-Май-20 (16)
Поэтому я и пытаюсь их прибить до выхода, но я даже не знаю кого. Думал на тему того, чтобы передавать пиды внучек через диск. но что-то и так уже слишком много файлов генерирую. Попробовал повесить wait на sigexit в мейне, что-то эксперименты не увенчались успехом и bgloop замечательно продолжает жить отдельно после нормального завершения мейна. Но sigint останавливает, это да.
- Завершение дочерних процессов 2 уровня, Licha Morada, 21:19 , 15-Май-20 (17)
> Поэтому я и пытаюсь их прибить до выхода, но я даже не > знаю кого.Можно поддержиавать в актуальном состоянии список всех детей. После каждого порождения, добавлять его PID в список: CHILDERN_PIDS="$CHILDERN_PIDS $!" https://stackoverflow.com/questions/2618403/how-to-kill-all-... Можно узнавать список "всех детей" непосредственно перед прибиванием. CHILDERN_PIDS=$(ps -o pid= --ppid $$) Потом по CHILDERN_PIDS можно итерировать в простом цикле for. Делать отдельно в каждом поколении в отношении непосредственных детей, либо рекурсивно из "дедушки". Тут хорошо описанно: https://unix.stackexchange.com/questions/124127/kill-all-des... Должно работать если: 1. Дети есть строго дети, в терминах иерархии процессов, а не демонизированные сироты. 2. Дети успевают сделать что-то осмысленное после того как их прибивают и до, собственно, умирания. Рекурсия из дедушки, в отличии от отдельной итерации в каждом поколении, смягчает ограничение 2. > Думал на тему того, чтобы передавать пиды внучек через > диск. но что-то и так уже слишком много файлов генерирую.
Не такой уж и порочный путь. Если написать некий диспетчер для отслеживания всего дерева, то можно будет отличать служебные файлы от временных данных и бардак станет более контролируемым.
- Завершение дочерних процессов 2 уровня, Аноним, 02:11 , 19-Май-20 (18)
> sigexitНет такого сигнала. EXIT — это обобщение bash'а для обработки сигналов, по которым он должен завершаться, а также нормального его завершения. Но я не пойму, зачем вешать wait в trap, когда его можно разместить в конце программы.
- Завершение дочерних процессов 2 уровня, Аноним, 22:57 , 13-Май-20 (12)
Заметил что при таком использовании работает корректно, только если в bgloop прилетают оба сигнала (sigint и sigkill), если kill $bgpid не отправлять из мейна (выходе), то фоновый процесс останется висеть и вместе с внучками перейдёт под инит. Или он может остановится sigint, и тогда из мейна его уже не убить на выходе. Если отправлять pkill -g $$ в мейне, то bgloop получает только int (не term) и до обработчика exit дело не доходит. Кроме того, 1 раз я успел заметить, что внучка перед смертью переходит под инит (в принципе это не плохо), это значит смерть не мгновенная?
- Завершение дочерних процессов 2 уровня, user user, 15:24 , 20-Май-20 (19)
чисто из любопытства, какой сценарий привел победе fork на pthread_create?
|