Mengapa pola “perintah || benar ”bermanfaat?

79

Saat ini saya sedang mengeksplorasi paket Debian, dan saya telah membaca beberapa contoh kode. Dan pada setiap baris, misalnya, postinstskrip adalah pola.

some command || true
another command || true

Jadi jika beberapa perintah gagal, maka baris mengembalikan true tetapi saya tidak melihat bagaimana ini mempengaruhi output dari program.

tukang kayu
sumber
5
FYI, ||:adalah cara idiomatis lain untuk menulis ini ( :menjadi entri lain dalam tabel builtin menunjuk ke true- tetapi dijamin akan menjadi builtin bahkan kembali ke Bourne; yang mengatakan, untuk POSIX sh, truejuga dijamin menjadi builtin - jadi itu adalah lebih terseness daripada efisiensi bahkan di zaman modern sekalipun).
Charles Duffy

Jawaban:

151

Alasan untuk pola ini adalah bahwa skrip pengelola dalam paket Debian cenderung untuk memulai set -e, yang menyebabkan shell keluar segera setelah perintah apa pun (secara tegas, pipa, daftar atau perintah majemuk) keluar dengan status bukan nol. Ini memastikan bahwa kesalahan tidak menumpuk: begitu ada masalah, skrip dibatalkan.

Dalam kasus di mana perintah dalam skrip dibiarkan gagal, menambahkan || truememastikan bahwa perintah majemuk yang dihasilkan selalu keluar dengan status nol, sehingga skrip tidak dibatalkan. Misalnya, menghapus direktori seharusnya bukan kesalahan fatal (mencegah paket dihapus); jadi kami akan gunakan

rmdir ... || true

karena rmdirtidak memiliki opsi untuk mengatakannya untuk mengabaikan kesalahan.

Stephen Kitt
sumber
4
Yah, tanpa set -etidak perlu || truesama sekali, saya pikir penting untuk memberikan konteksnya. Jika Anda melihat hal-hal aneh pada POWER, saya sangat menyarankan Anda untuk mengajukan bug ( reportbug)!
Stephen Kitt
16
@MichaelFelt, sebenarnya set -ebukan hanya "Konvensi Debian", tetapi pola pemrograman yang baik harus selalu digunakan. Lihat. misalnya davidpashley.com/articles/writing-robust-shell-scripts
kay
2
per pertanyaan di sini - mengapa menggunakan || trueset -e adalah konteks yang mungkin dan kemungkinan yang paling umum. Saya tunduk pada jawaban ini! Secara harfiah, ini berguna kapan saja status keluar dianggap tidak relevan DAN (seperti yang Anda tambahkan tautan artikel) Saya tidak menggunakan status keluar sebagai bagian dari kontrol skrip saya. Saya melihat utilitas (dalam set -e) tetapi tidak akan pergi sejauh artikel dan mengatakan "Setiap skrip yang Anda tulis harus menyertakan set -e di bagian atas". Ini adalah gaya pemrograman. "SELALU | Setiap" memasukkannya sendiri set perangkap - alias - absolut re: solusi wild-card pada ALWAYSakhirnya akan menjadi bumerang alias - tidak ada wahana gratis.
Michael Felt
1
@Kay Itu adalah perspektif yang saat ini populer tetapi pada akhirnya terperosok dengan banyak asumsi yang membatasi portabilitas skrip. Ada inkonsistensi historis dengan set -eperilaku. Mungkin tidak masalah bagi Anda, jika hanya target Anda bashdan kerang-kerang yang relatif baru yang hidup /bin/sh, tetapi situasinya lebih bernuansa ketika Anda ingin mendukung kerang / sistem lama.
mtraceur
2
@StephenKitt Tentu. Ada halaman yangset -e sangat teliti yang mendokumentasikan perilaku kerang yang berbeda oleh Sven Mascheck , meskipun halaman ini juga mendokumentasikan banyak kerang bersejarah / kuno yang tidak relevan saat ini. Ada juga dua halaman ini dengan fokus modern yang lebih sempit (mencari "set -e"): halaman "lintsh" , dokumentasi shell portabel autoconf -> Batasan subhalaman
Builtins
32

Meskipun tidak mempengaruhi output dari program yang baru saja dijalankan - ini memungkinkan pemanggil untuk melanjutkan seolah-olah semua baik-baik saja alias mempengaruhi logika masa depan.

Diulang: itu menutupi status kesalahan dari perintah sebelumnya.

michael@x071:[/usr/sbin]cat /tmp/false.sh
#!/bin/sh
false

michael@x071:[/usr/sbin]cat /tmp/true.sh 
#!/bin/sh
false || true

michael@x071:[/usr/sbin]sh /tmp/false.sh; echo $?
1
michael@x071:[/usr/sbin]sh /tmp/true.sh; echo $? 
0
Michael Felt
sumber
6
Itu benar, tetapi itu tidak menjawab mengapa menyembunyikan status keluar perintah berguna.
moopet
4
set -e berarti skrip akan langsung berakhir pada pengembalian yang tidak nol. Anda mungkin, di tempat terlokalisasi itu, tidak ingin itu terjadi!
rackandboneman
Saya orang yang sederhana - dan bagi saya satu-satunya alasan untuk menutupi status kesalahan adalah karena statusnya "di jalan". set -e membuat kesalahan "di jalan" jika sebelumnya Anda tidak peduli. Saya suka diskusi karena saya melihatnya sebagai cara yang bagus untuk membantu saya men-debug skrip saya dan menulis logika tambahan untuk menanggapi kesalahan (misalnya, || print - "xxx ada yang bukan nol di sini". Kemungkinan besar saya memiliki fungsi shell 'fatal' dan saya memiliki "sesuatu || fatal" tidak senang saya ".seo skrip harus melaporkan status gagal, atau tidak peduli. -e plus || benar adalah menutupi kesalahan. Jika itu yang saya inginkan - baiklah, jika tidak, saya kehilangan kesalahan
Michael Felt
yang harus saya tanyakan pada diri saya adalah: adalah || true - kruk pengkodean (cara malas untuk menyiasati / melewati kesalahan yang tidak ingin saya tangani sekarang; alat debug (-e tetapi tidak || benar) atau hanya dogma seseorang tentang praktik koding yang baik. Dengan kata lain - Saya melihatnya sebagai fitur - dengan manfaat potensial. Saya tidak melihatnya sebagai tongkat ajaib untuk menyembuhkan semua. Singkatnya - sama seperti kecantikan di mata yang melihatnya - set -edan || trueutilitas akan ditentukan oleh sifat dan tujuan dari programmer
Michael Felt
6
@MichaelFelt Pertimbangkan: git remote remove foo || true git remote add foo http://blah- kami ingin mengabaikan kesalahan jika remote tidak ada.
user253751