Bagaimana cara keluar dari skrip dalam pernyataan bersyarat?

50

Saya sedang menulis skrip bash di mana saya ingin keluar jika pengguna tidak root. Kondisional berfungsi dengan baik, tetapi skrip tidak keluar.

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

Saya sudah mencoba menggunakan &&bukannya ;tapi pekerjaan tidak.

Garrett Hall
sumber

Jawaban:

50

Anda bisa melakukannya dengan cara ini:

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

(ekspresi kondisional "biasa" dengan operator biner aritmatika dalam pernyataan pertama), atau:

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

(evaluasi aritmatika untuk tes pertama).

Perhatikan perubahannya ()-> {}- kurung keriting tidak menghasilkan subkulit. (Cari man bash"subkulit".)

Tikar
sumber
1
Silakan keluar dengan kode selain nol, contoh: exit 1untuk memahami proses induk bahwa terjadi masalah.
SamK
1
Anda tidak boleh menggunakan [[untuk perbandingan angka, gunakan ((.
Chris Down
1
@ ChrisDown [[baik-baik saja, asalkan Anda menggunakan -eqbukan ==.
Let_Me_Be
Memperbaiki kondisi, menambahkan versi aritmatika, @ChrisDown.
Mat
2
@Mat By the way, Anda dapat mempersingkat menjadi(( EUID )) && ...
Chris Down
21

Tanda kurung di sekitar perintah itu membuat subkulit . Subshell Anda bergema "Harus root untuk menjalankan skrip" dan kemudian Anda memberi tahu subshell untuk keluar (meskipun sudah, karena tidak ada lagi perintah). Cara termudah untuk memperbaikinya mungkin dengan hanya menggunakan if:

if [[ `id -u` != 0 ]]; then
    echo "Must be root to run script"
    exit
fi
Michael Mrozek
sumber
Jadi tidak ada cara untuk melakukan ini dengan satu-liner?
Garrett Hall
1
logika Anda mundur. dalam contoh Anda, jika id -u == 0, yang berarti bahwa Anda adalah root. Kamu ingin [[ $(id -u) != 0 ]]; then.
Tim Kennedy
4
Jika Anda / harus / memiliki satu-liner, coba ini untuk ukuran: [ "$UID" != 0 ] && echo 'You have to be root.' && exit 1;Perhatikan juga $UID, yang menyimpan proses pemijahan. Saya pikir Anda mungkin lebih suka $EUID.
janmoesen
1
@janmoesen, poin bagus. Dan sementara wee memiliki variabel dengan nilai numerik: ((UID)) && echo 'You have to be root.' && exit 1.
manatwork
3
@janmoesen: perhatikan bahwa menggunakan logika terbalik akan menyebabkan skrip set -edibatalkan. Salah satu solusi untuk masalah itu adalah [ "$UID" != 0 ] && echo 'You have to be root.' && exit 1 || true.
sam hocevar
2

Dengan bash :

[ $UID -ne 0 ] && echo "Must be root to run script" && exit 1
Cyrus
sumber
Itu akan gagal untuk keluar jika echogagal (misalnya karena stdout tidak dapat ditulisi).
Stéphane Chazelas
1

Tanda kurung ada ||dan &&tidak diperlukan karena ini asosiatif-benar. Dua ekspresi berikut ini setara:

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

Jadi &&alih-alih ;akan bekerja dengan baik, karena echoakan mengembalikan true.

[[ $(id -u) == 0 ]] || echo "Must be root to run script" && exit 1
ata
sumber
1
Walaupun semua yang Anda katakan benar, ini adalah pola yang buruk untuk dipelajari, karena Anda mengandalkan nilai pengembalian dari exp2. Apakah Anda yakin bahwa gema akan selalu mengembalikan status keluar 0? Ide yang jauh lebih baik untuk mengelompokkan pernyataan dengan kurung kurawal dan semi-titik dua. Ini adalah perangkap umum sehingga memiliki entri sendiri di BashPitfalls: mywiki.wooledge.org/BashPitfalls#cmd1_.26.26_cmd2_.7C.7C_cmd3
Flimm
1
@ Flimm: Saya tidak setuju itu pola yang buruk. Terbukti, penggunaannya tergantung pada huruf besar-kecil, dan juga tergantung pada pengetahuan Anda tentang nilai pengembalian yang akan Anda dapatkan. Dalam hal ini saya yakin gema akan mengembalikan 0 99,999% kali, dan jika itu menginjak kesalahan tulis (satu-satunya kasus itu tidak akan kembali 0) ada masalah yang lebih besar dari expr ini. Ada juga kasus di mana ANDA menghasilkan nilai kembali, jadi tidak, itu bukan "pola buruk" bagi saya.
ata
Saya akan menambahkan juga, seperti yang tertulis di wiki, bahwa Anda harus menggunakannya jika yakin untuk memahami evaluasi C. Bagaimanapun, sedikit pengujian harus menghapus semua ambiguitas.
ata
0

ini mungkin membantu Anda, dalam bash

[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
sandeep kazipeta
sumber
3
Ini sudah dijawab dan diterima. Juga, jawaban Anda hampir identik dengan apa yang sudah diposting.
maulinglawns
@maulinglawns, jawaban itu, bertentangan dengan yang lain memiliki manfaat portabel untuk semua shell Bourne-like (akan lebih baik jika kesalahan adalah output pada stderr, status keluar tidak nol dan substitusi perintah dikutip meskipun )
Stéphane Chazelas