Как выйти из скрипта в условном выражении?

50

Я пишу сценарий Bash, где я хочу выйти, если пользователь не root. Условно работает нормально, но скрипт не выходит.

[[ `id -u` == 0 ]] || (echo "Must be root to run script"; exit)

Я пытался использовать &&вместо, ;но ни одна из них не работает.

Гарретт Холл
источник

Ответы:

50

Вы можете сделать это следующим образом:

[[ $(id -u) -eq 0 ]] || { echo >&2 "Must be root to run script"; exit 1; }

(«обычное» условное выражение с арифметическим бинарным оператором в первом утверждении), или:

(( $(id -u) == 0 )) || { echo >&2 "Must be root to run script"; exit 1; }

(арифметическая оценка для первого теста).

Обратите внимание на изменение ()-> {}- фигурные скобки не порождают подоболочку. (Поиск man bash"subshell".)

Мат
источник
1
Пожалуйста, выйдите с кодом, отличным от нуля, например: exit 1чтобы понять родительский процесс, что возникла проблема.
SamK
1
Вы не должны использовать [[для числового сравнения, используйте ((.
Крис Даун
1
@ChrisDown [[в порядке, пока вы используете -eqвместо ==.
Let_Me_Be
Исправлено условное, добавлена ​​арифметическая версия @ChrisDown.
Мат
2
@Mat Кстати, вы можете сократить его до(( EUID )) && ...
Крис Даун
21

Скобки вокруг этих команд создают подоболочку . Ваш эшелон с эшелоном «Должен быть пользователем root для запуска скрипта», а затем вы указываете субоболочке выйти (хотя это уже произошло, поскольку больше не было команд). Самый простой способ исправить это, вероятно, просто использовать if:

if [[ `id -u` != 0 ]]; then
    echo "Must be root to run script"
    exit
fi
Михаил Мрозек
источник
Так нет ли способа сделать это с помощью одной строки?
Гаррет Холл
1
ваша логика обратная. в вашем примере, если id -u == 0, что будет означать , что вы есть корень. Вы хотите [[ $(id -u) != 0 ]]; then.
Тим Кеннеди
4
Если вы / должны / иметь однострочник, попробуйте это по размеру: [ "$UID" != 0 ] && echo 'You have to be root.' && exit 1;также обратите внимание $UID, что экономит порождение процесса. Я думаю, вы могли бы даже предпочесть $EUID.
Янмезен
1
@janmoesen, хорошая мысль. И в то время как дите имеют переменную с числовым значением: ((UID)) && echo 'You have to be root.' && exit 1.
Манатворк
3
@janmoesen: обратите внимание, что использование такой обратной логики приведет set -eк прерыванию сценария . Одним из решений этой проблемы является [ "$UID" != 0 ] && echo 'You have to be root.' && exit 1 || true.
Сам Хочевар
2

С баш :

[ $UID -ne 0 ] && echo "Must be root to run script" && exit 1
Кир
источник
Это не сможет завершиться, если произойдет echoсбой (например, потому что stdout не доступен для записи).
Стефан
1

Скобки вокруг ||и &&не обязательны, так как они являются ассоциативными справа. Следующие два выражения эквивалентны:

expr1 || expr2 && expr3
expr1 || { expr2 && expr3 }

Так что &&вместо того, ;чтобы работать просто отлично, так как echoвернет истину.

[[ $(id -u) == 0 ]] || echo "Must be root to run script" && exit 1
ата
источник
1
Хотя все, что вы сказали, правильно, это плохой шаблон для изучения, потому что вы полагаетесь на возвращаемое значение expr2. Вы уверены, что echo всегда будет возвращать статус 0? Намного лучше группировать утверждения с помощью фигурных скобок и точек с запятой. Это такая распространенная ошибка, что в BashPitfalls есть собственная запись: mywiki.wooledge.org/BashPitfalls#cmd1_.26.26_cmd2_.7C.7C_cmd3
Flimm
1
@Flimm: я не согласен, что это плохая модель. Очевидно, что его использование зависит от регистра, а также зависит от ваших знаний о возвращаемых значениях, которые вы получите. В этом случае я уверен, что echo вернет 0 в 99,999% случаев, и если он остановится из-за ошибки записи (единственный случай, когда он не вернет 0), то возникнет более серьезная проблема, чем этот expr. Также есть случай, когда ВЫ генерируете возвращаемые значения, так что нет, для меня это не «плохой шаблон».
ата
Я также добавлю, как сказано в вики, что вы должны использовать его, если обязательно разбираетесь в оценке C. В любом случае, небольшое тестирование должно устранить любые неясности.
ата
0

это может помочь вам, в Баш

[oracle@rac1 ~]$ which bash
/bin/bash
[oracle@rac1 ~]$ cat test1.sh
if [ `id -u` != 0 ]
then
echo "Must be root to run the script
 "
exit
fi
сандип казипета
источник
3
На это уже ответили и приняли. Кроме того, ваш ответ практически идентичен тому, который уже был опубликован.
Maulinglawns
@maulinglawns, этот ответ, в отличие от других, имеет преимущество переносимости для всех оболочек, подобных Борну )
Стефан