Saat mencoba sumber file, tidakkah Anda ingin kesalahan mengatakan file tidak ada sehingga Anda tahu apa yang harus diperbaiki?
Misalnya, nvm merekomendasikan untuk menambahkan ini ke profil / rc Anda:
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
Dengan di atas, jika nvm.sh
tidak ada, Anda akan mendapatkan "kesalahan diam". Tetapi jika Anda mencoba . "$NVM_DIR/nvm.sh"
, hasilnya akan menjadi FILE_PATH: No such file or directory
.
shell-script
JBallin
sumber
sumber
HOME
.Jawaban:
Dalam shell POSIX,
.
adalah builtin khusus, sehingga kegagalannya menyebabkan shell untuk keluar (dalam beberapa shell sepertibash
, itu hanya dilakukan ketika dalam mode POSIX).Apa yang memenuhi syarat sebagai kesalahan tergantung pada shell. Tidak semua dari mereka keluar karena kesalahan sintaks saat mem-parsing file, tetapi sebagian besar akan keluar ketika file yang bersumber tidak dapat ditemukan atau dibuka. Saya tidak tahu ada yang akan keluar jika perintah terakhir dalam file yang bersumber dikembalikan dengan status keluar yang tidak nol (kecuali jika
errexit
opsi ini aktif tentu saja).Di sini melakukan:
Merupakan kasus di mana Anda ingin sumber file jika ada, dan jangan jika tidak (atau kosong di sini dengan
-s
).Artinya, itu tidak boleh dianggap sebagai kesalahan (kesalahan fatal dalam kulit POSIX) jika file tidak ada, file itu dianggap sebagai file opsional.
Itu masih akan menjadi kesalahan (fatal) jika file tidak dapat dibaca atau direktori atau (dalam beberapa shell) jika ada kesalahan sintaksis saat menguraikannya yang akan menjadi kondisi kesalahan nyata yang harus dilaporkan.
Beberapa akan berpendapat bahwa ada kondisi balapan. Tapi satu-satunya artinya adalah bahwa shell akan keluar dengan kesalahan jika file dihapus di antara
[
dan.
, tapi saya berpendapat itu valid untuk menganggapnya kesalahan bahwa file jalur tetap ini tiba-tiba akan hilang saat skrip berlari.Di samping itu,
di mana
command
¹ menghapus atribut khusus ke.
perintah (sehingga tidak keluar dari shell on error) tidak akan berfungsi sebagai:.
kesalahan tetapi juga kesalahan dari perintah yang dijalankan di file bersumberSintaksis umum lainnya (lihat misalnya
grep -r /etc/default /etc/init*
pada sistem Debian untuk skrip init yang belum dikonversi kesystemd
(di manaEnvironmentFile=-/etc/default/service
digunakan untuk menentukan file lingkungan opsional sebagai gantinya)) meliputi:[ -e "$file" ] && . "$file"
Periksa file itu di sana, masih sumber jika kosong. Kesalahan masih fatal jika tidak bisa dibuka (meskipun ada di sana, atau ada di sana). Anda dapat melihat lebih banyak varian seperti
[ -f "$file" ]
(ada dan merupakan file biasa ),[ -r "$file" ]
(dapat dibaca), atau kombinasi keduanya.[ ! -e "$file" ] || . "$file"
Versi yang sedikit lebih baik. Membuatnya lebih jelas bahwa file tidak ada adalah kasus yang OK. Itu juga berarti
$?
akan mencerminkan status keluar dari perintah terakhir yang dijalankan$file
(dalam kasus sebelumnya, jika Anda mendapatkannya1
, Anda tidak tahu apakah itu karena$file
tidak ada atau jika perintah itu gagal).command . "$file"
Harapkan file ada di sana, tetapi jangan keluar jika tidak bisa diartikan.
[ ! -e "$file" ] || command . "$file"
Kombinasi di atas: tidak masalah jika file tidak ada di sana, dan untuk cangkang POSIX, kegagalan untuk membuka (atau mengurai) file tersebut dilaporkan tetapi tidak fatal (yang mungkin lebih diinginkan
~/.profile
).¹ Catatan:
zsh
Namun, Anda tidak dapat menggunakancommand
seperti itu kecuali dalamsh
persaingan; perhatikan bahwa di shell Korn,source
sebenarnya adalah alias untukcommand .
, varian non-khusus.
sumber
.bash_profile
. Saya kira lebih baik aman daripada menyesal, tetapi apakah bash pernah dalam mode POSIX saat.bash_profile
bersumber?bash
ketika tidak dalam mode POSIX. Anda ingin[ -e /file ] && . /file
jika Anda tidak menganggapnya sebagai kesalahan ketika file tidak ada. Sumber coba kemudian menangani kesalahan, jika ada yang tidak dapat dilakukan di sini..
sudah akan melaporkan kesalahan (pada stderr). Dan jika maksudnya adalah untuk tidak menganggapnya sebagai kesalahan ketika file tidak ada, itu tidak benar (dan itu tidak mungkin, dari status keluar untuk mengetahui apakah.
gagal karena file tidak ada atau tidak dapat dibaca, atau sudah tidak dapat diuraikan, atau perintah terakhir gagal) yang merupakan poin yang saya buat di sini dalam jawaban ini.nvm
Tanggapan Maintainer of :Interpretasi saya (dikombinasikan dengan penjelasan Stéphane yang sangat baik dan komentar Kusalananda):
Lebih sederhana dan lebih aman.
Itu membela terhadap kerang POSIX keluar pada startup karena file yang hilang (karena berbagai alasan). Mereka yang menggunakan shell non-POSIX (mis. Bash) dapat menghapus kondisional jika mereka mau.
sumber
/etc
, maka itu memungkinkan sebagian pengguna memiliki file, dan beberapa tidak memiliki file tersebut. IMHO,nvm
respons pengelola hanya menyentuh satu aspek.Seperti JBallin dan Stéphane Chazelas , dalam shell POSIX, sumber file yang tidak ada akan menyebabkan kegagalan login.
Tetapi menambahkan tes untuk melihat apakah file itu ada dan kemudian mencoba untuk sumbernya dapat menyebabkan sesuatu yang disebut kondisi balapan. Jika ada perubahan
nvm.sh
di antara[ -s nvm.sh ]
dan. nvm.sh
, itu akan menyebabkan persis bug yang mereka coba cegah, meskipun jauh lebih jarang.Secara umum, cara untuk mencegah kondisi balapan adalah dengan hanya mencoba hal yang ingin Anda lakukan, kemudian menangani kesalahan jika gagal, misalnya
Ternyata ini tidak berfungsi di shell POSIX, karena, seperti di atas,
.
kegagalan akan menyebabkan shell keluar segera, sebelum penanganan kesalahan dapat berjalan.Jawaban saya berpendapat bahwa kerang POSIX tidak relevan dengan pertanyaan ini, karena
.bash_profile
seharusnya tidak pernah berjalan dalam mode POSIX. Jadi kita bisa melakukan kode di atas saja.Agar paling aman, kami dapat memastikan bahwa mode POSIX tidak berlaku, atau memastikan mode POSIX dinonaktifkan menggunakan teknik yang dijelaskan dalam /unix//a/383581/3169 .
Jawaban Stéphane memiliki beberapa saran yang berguna untuk bagaimana menangani semua kerang POSIX, yang saya pikir adalah maksud penulis nvm, tetapi agak berbeda dari apa yang ditanyakan di sini, itulah sebabnya kami memiliki beberapa pendekatan yang mungkin, tergantung pada tujuan Anda. .
sumber