Як вийти зі скрипту в умовному операторі?


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"нижню оболонку".)


1
Вийдіть із кодом, відмінним від нуля, наприклад: exit 1щоб зрозуміти батьківський процес, що сталася проблема.
СамК

1
Не слід використовувати [[для порівняння чисел, використовувати ((.
Кріс Даун

1
@ChrisDown [[- це добре, якщо ви використовуєте -eqзамість цього ==.
Let_Me_Be

Виправлено умовне, додано арифметичну версію @ChrisDown.
Мат

2
@Mat До речі, ви можете скоротити його до(( EUID )) && ...
Chris Down

21

В дужках навколо цих команд створюється піддіаграма . Ваша піддіаграма лунає "Повинен запустити скрипт", і тоді ви скажете підпакеті вийти (хоча це вже було б, оскільки команд більше не було). Найпростіший спосіб виправити це, мабуть, просто використовувати 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.
janmoesen

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.
sam hocevar

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. Ви впевнені, що відлуння завжди поверне статус виходу 0? Набагато краще ідеї згрупувати заяви із фігурними дужками та напівколонами. Це настільки поширений підводний камінь, що він має свій власний запис у BashPitfalls: mywiki.wooledge.org/BashPitfalls#cmd1_.26.26_cmd2_.7C.7C_cmd3
Flimm

1
@Flimm: Я не згоден, що це погана модель. Очевидно, що його використання залежить від регістру, а також залежить від ваших знань про повернені значення, які ви отримаєте. У цьому випадку я впевнений, що ехо поверне 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, ця відповідь, всупереч іншим, заслуговує на те, що вона переноситься на всі оболонки Борна (було б краще, якби помилка виводилася на stderr, статус виходу був не нульовим, а заміна команди була цитована, хоча )
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.