Skrip Bash dengan `set -e` tidak berhenti pada perintah` ... && ... `

13

Saya menggunakan set -euntuk menghentikan skrip bash pada kesalahan pertama .

Semua berfungsi OK kecuali saya menggunakan perintah dengan &&:

$ cat script
set -e
cd not_existing_dir && echo 123
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
I'm running! =P
$

dibandingkan dengan:

$ cat script
set -e
cd not_existing_dir
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
$

Contoh pertama masih menggema I'm running!, tetapi yang kedua tidak. Mengapa mereka berperilaku berbeda?

UPD. Pertanyaan serupa: /programming/6930295/set-e-and-short-tests

907
sumber
Apa yang Anda harapkan terjadi pada contoh pertama?
Flup
@ Flup Saya berharap skrip untuk berhenti setelah cdperintah gagal
907
1
Lihat BashFAQ # 105 untuk diskusi umum tentang tempat-tempat di mana set -eperilaku mengejutkan.
Charles Duffy
terkait: stackoverflow.com/questions/25794905/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Jawaban:

9

Ini adalah perilaku yang terdokumentasi. The bash (1) halaman manual mengatakan, untuk set -e,

Shell tidak keluar jika perintah yang gagal adalah bagian dari daftar perintah segera mengikuti kata kunci whileatau until, bagian dari pengujian mengikuti kata-kata ifatau elifdicadangkan, bagian dari perintah yang dieksekusi dalam daftar &&atau|| kecuali perintah mengikuti akhir &&atau|| , setiap perintah dalam pipa tetapi yang terakhir, atau jika nilai pengembalian perintah sedang terbalik !.
[Penekanan ditambahkan.]

Dan Spesifikasi Bahasa Perintah POSIX Shell mengkonfirmasi bahwa ini adalah perilaku yang benar:

The -ePengaturan harus diabaikan ketika menjalankan daftar senyawa berikut while, until, if, atau elifkata reserved, pipa dimulai dengan !kata reserved, atau perintah dari sebuah AND-OR daftar selain yang terakhir.

dan Bagian 2.9.3 Daftar dokumen yang didefinisikan

Daftar AND-OR adalah urutan satu atau lebih pipa yang dipisahkan oleh operator " &&" dan " ||".

G-Man Mengatakan 'Reinstate Monica'
sumber
9

The set -epilihan tidak memiliki efek dalam beberapa situasi, dan ini adalah perilaku standar dan portabel di POSIX compliant shell.


Perintah yang gagal adalah bagian dari pipa:

false | true; echo printed

akan dicetak printed.

Dan hanya kegagalan dari pipa itu sendiri yang dipertimbangkan:

true | false; echo 'not printed'

tidak akan mencetak apa pun.


Gagal menjalankan perintah dalam daftar senyawa berikut while, until, if, elifkata reserved, pipa yang diawali dengan !kata reserved, atau perintah apapun sebagai bagian dari &&atau ||daftar kecuali yang terakhir:

false || true; echo printed

Perintah terakhir gagal masih membuat set -eterpengaruh:

true && false; echo 'not printed'

The subkulit gagal dalam perintah senyawa:

(false; echo 'not printed') | cat -; echo printed
cuonglm
sumber
Terima kasih! Akan lebih jelas untuk menggunakan echo "printed"dan echo "not_printed"dalam contoh Anda (bukan echo 1).
907
3
Catatan yang set -emenyebabkan keluar (false && true); echo not here, tetapi tidak di { false && true; }; echo here, meskipun YMMV dengan shell yang berbeda dan bahkan versi yang berbeda dari shell yang sama. Saya tidak akan menyentuh set -edengan tongkang tongkang dan akan melakukan penanganan kesalahan yang tepat sebagai gantinya.
Stéphane Chazelas
1

Dugaan saya adalah jika-maka kondisi secara keseluruhan bernilai true.

Saya mencoba

set -e
if cd not_existing_dir
then  echo 123
fi
echo "I'm running! =P"

siapa yang memberi

-bash: cd: not_existing_dir: No such file or directory
I'm running! =P

kode kesalahan ditangkap oleh kondisi jika, maka bash tidak akan memicu akhir eksekusi.

Archemar
sumber
Tapi saya tidak menggunakanif ... fi
907
Saya tahu, ini adalah implisit jika.
Archemar