Saya membuat skrip berikut:
# !/bin/bash
# OUTPUT-COLORING
red='\e[0;31m'
green='\e[0;32m'
NC='\e[0m' # No Color
# FUNCTIONS
# directoryExists - Does the directory exist?
function directoryExists {
cd $1
if [ $? = 0 ]
then
echo -e "${green}$1${NC}"
else
echo -e "${red}$1${NC}"
fi
}
# EXE
directoryExists "~/foobar"
directoryExists "/www/html/drupal"
Scriptnya bekerja, tetapi di samping gema saya, ada juga output kapan
cd $1
gagal dieksekusi.
testscripts//test_labo3: line 11: cd: ~/foobar: No such file or directory
Apakah mungkin untuk menangkap ini?
bash
shell
shell-script
error-handling
Thomas De Wilde
sumber
sumber
test -d /path/to/directory
(atau[[ -d /path/to/directory ]]
dalam bash) akan memberi tahu Anda apakah target yang diberikan adalah direktori atau tidak, dan itu akan melakukannya dengan tenang.cd
ke dalamnya.directoryExists
.Jawaban:
Script Anda mengubah direktori saat dijalankan, yang berarti itu tidak akan berfungsi dengan serangkaian nama path relatif. Anda kemudian berkomentar kemudian bahwa Anda hanya ingin memeriksa keberadaan direktori, bukan kemampuan untuk menggunakan
cd
, jadi jawaban tidak perlu digunakancd
sama sekali. Diperbaiki. Menggunakantput
dan warna dariman terminfo
:(Diedit untuk menggunakan yang lebih kebal
printf
daripada masalahecho
yang mungkin bertindak pada urutan melarikan diri dalam teks.)sumber
Gunakan
set -e
untuk mengatur mode exit-on-error: jika perintah sederhana mengembalikan status bukan nol (menunjukkan kegagalan), shell keluar.Waspadalah yang
set -e
tidak selalu berhasil. Perintah di posisi tes diizinkan untuk gagal (mis.if failing_command
,failing_command || fallback
). Perintah dalam subkulit hanya menyebabkan keluarnya subkulit, bukan induknya:set -e; (false); echo foo
tampilanfoo
.Atau, atau sebagai tambahan, dalam bash (dan ksh dan zsh, tetapi bukan sh polos), Anda dapat menentukan perintah yang dijalankan jika perintah mengembalikan status bukan nol, dengan
ERR
jebakan, mistrap 'err=$?; echo >&2 "Exiting on error $err"; exit $err' ERR
. Perhatikan bahwa dalam kasus seperti(false); …
, perangkap ERR dieksekusi di subkulit, sehingga tidak dapat menyebabkan induk untuk keluar.sumber
||
perilaku, yang memungkinkan untuk dengan mudah melakukan penanganan kesalahan yang tepat tanpa menggunakan perangkap. Lihat jawaban saya . Apa pendapat Anda tentang metode itu?ERR
sinyal semu didukung di semua shell utama. Terima kasih atas ulasannya! =)Untuk memperluas jawaban @Gilles ' :
Memang,
set -e
tidak berfungsi di dalam perintah jika Anda menggunakan||
operator setelahnya, bahkan jika Anda menjalankannya dalam subkulit; mis. ini tidak akan berfungsi:Tetapi
||
operator diperlukan untuk mencegah kembali dari fungsi luar sebelum pembersihan.Ada sedikit trik yang dapat digunakan untuk memperbaikinya: jalankan perintah dalam di latar belakang, dan kemudian segera tunggu. The
wait
builtin akan mengembalikan kode keluar dari perintah batin, dan sekarang Anda menggunakan||
setelahwait
, bukan fungsi batin, jadiset -e
bekerja dengan baik dalam kedua:Inilah fungsi generik yang dibangun di atas gagasan ini. Ini harus bekerja di semua shell yang kompatibel dengan POSIX jika Anda menghapus
local
kata kunci, yaitu ganti semualocal x=y
hanya denganx=y
:Contoh penggunaan:
Menjalankan contoh:
Satu-satunya hal yang perlu Anda perhatikan ketika menggunakan metode ini adalah bahwa semua modifikasi variabel Shell yang dilakukan dari perintah yang Anda lewati
run
tidak akan merambat ke fungsi panggilan, karena perintah berjalan dalam subkulit.sumber
Anda tidak mengatakan apa yang sebenarnya Anda maksud dengan
catch
--- laporkan dan lanjutkan; batalkan proses lebih lanjut?Karena
cd
mengembalikan status tidak nol pada kegagalan, Anda dapat melakukan:Anda bisa keluar dari kegagalan:
Atau, gema pesan Anda sendiri dan keluar:
Dan / atau menekan kesalahan yang diberikan oleh
cd
pada kegagalan:Secara standar, perintah harus meletakkan pesan kesalahan pada STDERR (file descriptor 2). Demikian
2>/dev/null
kata redirect STDERR ke "bit-bucket" yang dikenal oleh/dev/null
.(jangan lupa mengutip variabel Anda dan tandai akhir opsi untuk
cd
).sumber
Sebenarnya untuk kasus Anda, saya akan mengatakan bahwa logika dapat ditingkatkan.
Alih-alih cd dan kemudian periksa apakah itu ada, periksa apakah ada kemudian masuk ke direktori.
Tetapi jika tujuan Anda adalah untuk membungkam kesalahan yang mungkin terjadi
cd -- "$1" 2>/dev/null
, tetapi ini akan membuat Anda men-debug di masa depan lebih sulit. Anda dapat memeriksa bendera pengujian jika di: Bash jika dokumentasi :sumber
$1
variabel dan akan gagal jika variabel itu berisi karakter meta kosong atau karakter shell lainnya. Ini juga gagal memeriksa apakah pengguna memiliki izin untukcd
masuk ke dalamnya.