2

Как сделать автоматический возврат source d-скрипта, если какая-либо команда внутри него завершится неудачно?

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

#!/bin/bash
# foo.env
set -e        # auto-exit on any command failure
echo "hi"
grep 123 456  # this command will fail (I don't have a file named "456")
echo "should not reach here"

Если я выполню команду в обычном режиме, она автоматически завершится с ошибкой команды grep :

box1% ./foo.env
hi
grep: 456: No such file or directory

Однако, если я source сценарий, он выходит из моей текущей оболочки, а не только из сценария:

box1% ssh box2
box2% source ./foo.env
hi
grep: 456: No such file or directory
Connection to box2 closed.
box1%

Если я уберу set -e ,

#!/bin/bash
# foo2.env
echo "hi"
grep 123 456  # this command will fail (I don't have a file named "456")
echo "should not reach here"

тогда он вообще не выполняет автоматический выход или автоматический возврат source сценария d:

box1% ssh box2
box2% source ./foo2.env
hi
grep: 456: No such file or directory
should not reach here
box2%

Единственный обходной путь, который я нашел, - это добавить выражение return к каждой строке кода в сценарии, например,

box1% cat foo3.env
#!/bin/bash
# foo3.env - works, but is cumbersome
echo "hi" || return
grep 123 456 || return
echo "should not reach here" || return

box1% source foo3.env
hi
grep: 456: No such file or directory
box1%

Есть ли другой способ для сценариев с source d, аналогичный тому, как set -e работает для сценариев без source ?

1 ответ1

1

Когда вы source из скрипта, это как если бы вы писали этот файл построчно с клавиатуры. Это означает, что set -e будет учитывать текущую оболочку и в случае ошибки выйдет из текущей оболочки.

Это обходной путь. Сегодня я чувствую себя ленивым, поэтому я подумал, что компьютер может написать ||return для меня, или, лучше, построчно прочитать файл и выполнить так:

#!/bin/bash
# this is the file MySource.sh
while IFS='' read -r line
do
   [[ $line == \#* ]] || $line || return
done < "$1"

выполнить его с . MySource.sh FileToBeSourced.sh

Если ваш скрипт FileToBeSourced.sh состоит из однострочных команд, он должен работать.
Очень далеко, чтобы быть готовым к использованию в производственной среде.
Протестируйте и в конечном итоге используйте на свой страх и риск.

Он пропускает строки, начинающиеся с # потому что они должны вызвать команду error # command not found .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .