2016-09-29 4 views
1

Мой сценарий bash (init.sh) вызывает другой скрипт (script.sh), и я хочу проверить код ошибки от script.sh перед выполнением дальнейших действий в init.sh.
Я думал о тестировании его $?, но он не работаетВ сценарии bash введите код ошибки из вызванного сценария

Мои init.sh, как следующее:

#!/bin/bash 
set -e 
echo "Before call" 
docker run -v $PWD:/t -w /t [command] 
if [ $? == 1 ]; then 
     echo "Issue" 
fi 
echo "After call" 

я получил только Before call от stdout и не After call.

Я знаю, за то, что если я исполню docker run -v $PWD:/t -w /t [command] наедине с неправильными аргументами, то echo $? будет правильно отображать 1.

Я думал, что я не улавливаю код выхода из scrip.sh, но откуда-то еще.

Любые идеи?

+1

Это запутанно ... вы упоминаете 'script.sh', но не называете его в' init.sh'. Во всяком случае, вы можете попробовать запустить bash -x init.sh' и посмотреть, что он на самом деле делает. – gilez

+1

С 'set -e', если вызов' docker' * устанавливает * $? 'В 1, ваш скрипт будет завершен до выполнения оператора' if', не говоря уже о последнем вызове 'echo'. – chepner

ответ

2

бежит скрипт с set -e. Это означает, что если какая-либо команда выйдет с ненулевым статусом, bash прекратит выполнение всех последующих строк. Итак, здесь, если docker выходит со статусом 1, условие, которое следует ниже, не будет иметь возможности запускаться вообще. Попробуйте вместо этого:

#!/bin/bash 
set -e 
echo "Before call" 
if ! docker run -v $PWD:/t -w /t [command]; then 
     echo "Issue" 
fi 
echo "After call" 

Это запускает команду внутри, если тест, который подавляет эффект set -e я описал выше, и дает вам шанс поймать ошибку. Обратите внимание, что это также улавливает все ненулевые статусы, а не только 1.

+0

Спасибо за ** очень ** ценную информацию. Это трюк! – Mornor

+0

'set -e' is [* not * вообще хорошая идея] (http://mywiki.wooledge.org/BashFAQ/105). – chepner

+0

@chepner Вы правы. На самом деле, я думаю, этот вопрос сам по себе является примером почему. – redneb

1

Bash числового оператор сравнение -eq, а не == ...
Итак:

#!/bin/bash 
set -e 
echo "Before call" 
docker run -v $PWD:/t -w /t [command] 
if [ $? -eq 1 ]; then 
     echo "Issue" 
fi 
echo "After call" 
+0

Это, безусловно, хороший момент. Я попытался и не смог :( – Mornor

+0

Это несколько неуместно: нет никаких значений, которые ''? 'Могли бы иметь, что бы вызывать' $? -eq 1' и '$? = 1' (используйте' = 'с' [ ', а не' == '), чтобы вести себя по-другому. – chepner

+0

@ Морнор: почему это не получилось? Потому что команда не выходила с '-1'? Или почему? Вы должны повторить значение '$?', Чтобы проверить его значение ... – MarcoS

1

set -e, как правило, плохая идея. Конечно, может показаться хорошей идеей, чтобы ваш скрипт автоматически выходил в случае непредвиденной ошибки, но проблема в том, что set -e, и у вас могут быть разные представления о том, что представляет собой фатальную ошибку.

Вместо этого выполните свою обработку ошибок.

#!/bin/bash 
echo "Before call" 
docker run -v $PWD:/t -w /t [command] 
docker_status=$? 
if [ $docker_status != 0 ]; then 
    echo "docker returned: $docker_status" 
    exit $docker_status 
fi 
echo "After call" 

В этом простом коде, я несколько избыточно сохранил значение $? других переменный первым. Это гарантирует, что он будет сохранен после того, как вы начнете выполнять другие команды, которые исследуют, регистрируют или иным образом обрабатывают значение $?. Кроме того, я регистрирую и выхожу здесь на любым отличным от нуля статусом, а не только 1. Теоретически вы можете предпринять разные действия для статуса выхода 1, чем для статуса выхода 2, но здесь мы берем то же самое log-then-exit для любой ошибки.

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