2013-07-19 2 views
3

В этом сценарии У нас есть сценарий trap.shПочему ловушка не работает в трубопроводе

#!/bin/bash 
trap "echo trapped" EXIT 
exit 0 

и test.sh. Если test.sh подобен

#!/bin/bash 
. trap.sh 

или

#!/bin/bash 
./trap.sh | : 

ловушка работает

Но если test.sh подобен

#!/bin/bash 
. trap.sh | : 

ловушка не сработала.

Кто-нибудь знает, почему это так?

+0

Является ли какой-либо сценарий когда-либо выполняемым, так что рабочий каталог (cwd) не находится там, где есть скрипты? – wallyk

+0

@wallyk Нет, это не сценарий. – dspjm

ответ

0

Команда на левой стороне трубы выполняется в подоболочки:

exit | grep 

Выход SIGTRAP, похоже, не будет распространяться на подоболочек.

trap 'echo T >&2' EXIT ; (exit) # Nothing. 
+0

Я заметил проблему подоболочки. Но когда мы позвоним. trap.sh | :, я думаю, мы называем trap.sh в подоболочке, а подоболочка, называемая ловушкой, при выходе из подоболочки, вызывает вызов trap, как мы называем ./trap.sh | :. Я не понимаю, почему есть разные результаты. – dspjm

1

Лучше изменить команду тестирования на . trap.sh|cat (стандартный вывод из trap.sh не может быть отображена с :). Но даже тогда нет выхода, поэтому вы правы: ловушка не работает. Это должно быть ошибкой в ​​bash и должно сообщаться сопровождающим.

Интересно, что когда мы echo $$ внутри trap.sh сценария, мы видим, что он выполнен по той же оболочке, выполняющей весь трубопровод . trap.sh|cat, противоречащее заявление руководства: Каждая команда в конвейере выполняется как отдельный процесс (т. е. в подоболочке).Это была ошибка, см. Комментарии. Возможно, это связано с некоторой оптимизацией, чтобы свести к минимуму создание подоболочек, но это всего лишь предположение.

+1

'$$' всегда оценивает идентификатор процесса родительской оболочки, даже если дочерний процесс выполняется в другом процессе. – chepner

+0

+1, как я думаю, я согласен, что это может быть ошибкой. Я заменил эхо 'touch trap.fired', чтобы убедиться, что это не проблема, когда стандартный вывод просто теряется где-то. С '. trap.sh | : ', файл не был создан. – chepner

+0

Хотя в руководстве bash указано: _ $ Расширяется до идентификатора процесса shell_, вы, очевидно, правы, что '$$' в этом случае оценивает идентификатор процесса исходной оболочки. Благодаря вашему комментарию я обнаружил переменную оболочки * BASHPID *, о которой говорится в руководстве: _Раздает идентификатору процесса текущего процесса bash. Это отличается от $$ при определенных обстоятельствах, таких как подоболочки, которые не требуют перезапуска bash. Действительно, 'echo $ BASHPID' показывает разные значения. – Armali

1

I модифицировано trap.sh, чтобы включить опцию xtrace.

#!/bin/bash 
set -x 
trap 'echo trapped' EXIT 
exit 0 

Запуск trap.sh как скрипт производит

~ $ ./trap.sh | кот + ловушка 'эхо в ловушке' EXIT + выход 0 + эхо в ловушке ловушке

Sourcing это первый, однако производит

~ $ . trap.sh | cat 
++ trap 'echo trapped' EXIT 
++ exit 0 

Это указывает на то, что trap выполняется в более глубоком субоболочке (почему, Я не знаю), и что сама ловушка никогда не выполняется (я подтвердил во втором эксперименте touch, введя в файл int he trap вместо того, чтобы просто эхом, в случае возникновения проблемы с наследованием стандартного вывода; никогда не касался).

Я думаю, что так или иначе EXIT сигнал игнорируется до source выполняемой команды, основываясь на этом предложении из описания команды trap на странице человека:

сигналы игнорировались при записи к оболочке не может быть захвачен или сброшен.

В результате выполняется команда trap, но сама ловушка никогда не регистрируется и поэтому не срабатывает.

Смежные вопросы