В моем вызываемом скрипте "trap 'echo ignore' USR1", почему вызывающий скрипт убивается?

Скажем, у меня есть два сценария bash:

/ TMP / ловец:

#!/bin/bash
trap 'echo trapper: ignoring USR1' USR1
"$(dirname $0)"/usr1er & p=$!
sleep 1
echo trapper: now killing usr1er
kill $p
echo trapper: sleeping
sleep 1
echo trapper: reached end of trapper

/ TMP / usr1er:

#!/bin/bash
trap 'echo "usr1er: EXIT received, sending USR1"; kill -USR1 0' EXIT
while sleep 1;do echo usr1er: sleeping;done

trapper должен перехватывать USR1 и просто игнорировать его. Он запускает usr1er, который убивает свою группу процессов сигналом USR1. Теперь, если я запускаю trapper как скрипт самостоятельно из интерактивной оболочки, он убивает usr1er и завершается нормально:

$ /tmp/trapper; echo done
trapper: now killing usr1er
trapper: sleeping
usr1er: EXIT received, sending USR1
/tmp/trapper: line 9: 16596 Terminated              "$(dirname $0)"/usr1er
trapper: ignoring USR1
trapper: reached end of trapper
done

Хотя если я попробую $(/tmp/trapper)Выходит из всей оболочки. Точно так же, если я сделаю отдельный скрипт, который вызывает /tmp/trapper, лайк /tmp/outer:

#!/bin/bash
"$(dirname $0)"/trapper
echo outer: reached end of outer

его убивают, не печатая "достигнутый конец внешнего":

$ /tmp/outer
trapper: now killing usr1er
trapper: sleeping
usr1er: EXIT received, sending USR1
User defined signal 1
/tmp/trapper: line 9: 23544 Terminated              "$(dirname $0)"/usr1er
User defined signal 1
trapper: ignoring USR1
trapper: reached end of trapper

Зачем?

2 ответа

Попробуйте это изменение

/ TMP /usr1er:

#!/bin/bash
trap 'echo "usr1er: EXIT received, sending USR1"; kill -USR1 $PPID' TERM
while sleep 1;do echo usr1er: sleeping;done

Обрабатывается сигнал TERM вместо EXIT и отправляется USR1 $PPID вместо 0

Кажется, что $() не запускает процесс с отдельной группой процессов / PGID (очевидно, для создания C-c Работа).

Кроме того, любая неинтерактивная оболочка также не будет запускать отдельные PGID для своих детей (если вы не включите управление заданиями с помощью команды set -m):

$ bash -c '/tmp/trapper;echo done'
trapper: now killing usr1er
trapper: sleeping
usr1er: EXIT received, sending USR1
User defined signal 1
$ /tmp/trapper: line 9: 17522 Terminated              "$(dirname $0)"/usr1er
trapper: ignoring USR1
trapper: reached end of trapper

Обратите внимание, что "done" не печатается, внешний bash-скрипт, который не перехватывает USR1, убивается, пока trapper продолжает жить до конца.

Вы можете проверить PGID каждого процесса, поставив ps -o %p%r%c -p$$ в скриптах:

$ /tmp/outer
  PID  PGID COMMAND
27630 27630 outer
  PID  PGID COMMAND
27633 27630 trapper
  PID  PGID COMMAND
27635 27630 usr1er
trapper: now killing usr1er
trapper: sleeping
usr1er: EXIT received, sending USR1
User defined signal 1
$ /tmp/trapper: line 9: 27635 Terminated              "$(dirname $0)"/usr1er
trapper: ignoring USR1
trapper: reached end of trapper
Другие вопросы по тегам