Как сделать так, чтобы 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
-d скриптов?
решение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
Если вашФайлToBeSourced.shСкрипт состоит из одной строки команд, он должен работать.
Далеко-далеко, чтобы быть готовым к использованию в производственной среде.
Протестируйте его и в конечном итогеИспользуйте его на свой страх и риск.
Он пропускает строки, начинающиеся с , #
поскольку они должны вызывать ошибку # command not found
.