2015-12-20 8 views
3

Я пытаюсь понять, почему всякий раз, когда я использую function 2>&1 | tee -a $LOG, tee создает функцию подоболочки в функции, которая не может быть удалена простым exit 1 (и если я не использую tee, он отлично работает). Ниже приведен пример:В bash как выйти из скрипта из функции, которая передается по типу?

#!/bin/bash 
LOG=/root/log.log 

function first() 
{ 
echo "Function 1 - I WANT to see this." 
exit 1 
} 

function second() 
{ 
echo "Function 2 - I DON'T WANT to see this." 
exit 1 
} 
first 2>&1 | tee -a $LOG 
second 2>&1 | tee -a $LOG 

Выход:

[[email protected] ~]# ./1.sh 
Function 1 - I WANT to see this. 
Function 2 - I DON'T WANT to see this. 

Зв если я удалю часть | tee -a $LOG, она будет работать как ожидалось (сценарий будет выведен в первой функции).

Можете ли вы, пожалуйста, объяснить, как преодолеть это и правильно выйти из функции во время получения выходного сигнала?

+0

"создает функцию подоболочки в функции" Ну, вы уже сказали это. Зачем? Поскольку все простые команды в конвейере, кроме последнего, выполняются в подоболочках (последний зависит от опции или чего-то - я забыл). Зачем? Потому как. Что касается того, как правильно выйти, проверьте статус выхода (если установлен 'pipefail') или' PIPESTATUS' после конвейера. – 4ae1e1

+0

Последующий комментарий выше: вариант, который я забыл, - 'lastpipe'. – 4ae1e1

+0

Связанные: http://stackoverflow.com/q/9277827/951890 –

ответ

3

Если вы создаете конвейер, функция запускается в подоболочке, и если вы используете exit из подоболочки, будет затронута только подоболочка, а не родительская оболочка.

printPid(){ echo $BASHPID; } 

printPid #some value 
printPid #same value 
printPid | tee #an implicit subshell -- different value 
(printPid) #an explicit subshell -- also a different value 

Если вместо aFunction | tee вы делаете:

aFunction > >(tee) 

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

+0

Спасибо, PSkocik, это действительно необходимое решение! – LinenG

1

Вы можете сказать, Баш на провал, если что-нибудь в трубопроводе не может с set -e -o pipefail:

$ cat test.sh 
#!/bin/bash 
LOG=~/log.log 

set -e -o pipefail 

function first() 
{ 
echo "Function 1 - I WANT to see this." 
exit 1 
} 

function second() 
{ 
echo "Function 2 - I DON'T WANT to see this." 
exit 1 
} 
first 2>&1 | tee -a $LOG 
second 2>&1 | tee -a $LOG 
$ ./test.sh 
Function 1 - I WANT to see this. 
+0

Спасибо! Мне также нравится это решение - элегантное, но работает только на bash v3 и выше (по-видимому). – LinenG

+0

bash v3 был выпущен в 2004 году. Думаю, с тобой все будет в порядке. –

2

Использование PIPESTATUS для получения статуса выхода первой команды в трубопроводе.

first 2>&1 | tee -a $LOG; test ${PIPESTATUS[0]} -eq 0 || exit ${PIPESTATUS[0]} 
second 2>&1 | tee -a $LOG; test ${PIPESTATUS[0]} -eq 0 || exit ${PIPESTATUS[0]}