Apakah ada cara untuk men-debug skrip bash? Misalnya sesuatu yang mencetak semacam log eksekusi seperti "saluran telepon 1", "saluran telepon 2" dll.
Apakah ada cara untuk men-debug skrip bash? Misalnya sesuatu yang mencetak semacam log eksekusi seperti "saluran telepon 1", "saluran telepon 2" dll.
Jawaban:
sh -x script [arg1 ...]
bash -x script [arg1 ...]
Ini memberi Anda jejak apa yang sedang dieksekusi. (Lihat juga 'Klarifikasi' di dekat bagian bawah jawaban.)
Terkadang, Anda perlu mengontrol proses debug dalam skrip. Dalam hal ini, seperti yang diingatkan Cheeto kepada saya, Anda dapat menggunakan:
set -x
Ini mengaktifkan debugging. Anda kemudian dapat mematikannya lagi dengan:
set +x
(Anda dapat mengetahui status penelusuran saat ini dengan menganalisis $-, bendera saat ini, untukx .)
Juga, shells umumnya menyediakan opsi ' -n' untuk 'no eksekusi' dan ' -v' untuk 'verbose' mode; Anda dapat menggunakan ini dalam kombinasi untuk melihat apakah shell berpikir itu bisa mengeksekusi skrip Anda - kadang-kadang berguna jika Anda memiliki kutipan yang tidak seimbang di suatu tempat.
Ada anggapan bahwa opsi ' -x' di Bash berbeda dari shell lainnya (lihat komentar). The Bash Manual mengatakan:
-x
Cetak jejak perintah sederhana, forperintah, caseperintah, selectperintah, dan forperintah aritmatika dan argumennya atau daftar kata yang terkait setelah diperluas dan sebelum dieksekusi. Nilai PS4variabel diperluas dan nilai yang dihasilkan dicetak sebelum perintah dan argumen yang diperluas.
Sebanyak itu sepertinya tidak menunjukkan perilaku yang berbeda sama sekali. Saya tidak melihat referensi lain yang relevan dengan ' -x' di manual. Itu tidak menjelaskan perbedaan dalam urutan startup.
Klarifikasi : Pada sistem seperti kotak Linux biasa, di mana ' /bin/sh' adalah symlink ke ' /bin/bash' (atau di mana Bash dieksekusi ditemukan), dua baris perintah mencapai efek setara menjalankan skrip dengan jejak eksekusi aktif. Pada sistem lain (misalnya, Solaris, dan beberapa varian Linux yang lebih modern), /bin/shbukan Bash, dan dua baris perintah akan memberikan (sedikit) hasil yang berbeda. Terutama, ' /bin/sh' akan bingung dengan konstruk di Bash yang tidak dikenali sama sekali. (Pada Solaris, /bin/shadalah shell Bourne; di Linux modern, kadang-kadang Dash - shell yang lebih kecil, lebih khusus hanya POSIX.) Ketika dipanggil dengan nama seperti ini, baris 'shebang' (' #!/bin/bash' vs '#!/bin/sh'
Manual Bash memiliki bagian pada mode Bash POSIX yang, berbeda dengan versi lama dari jawaban ini (lihat juga komentar di bawah), tidak menjelaskan secara rinci perbedaan antara 'Bash dipanggil sebagai sh' dan 'Bash dipanggil sebagai bash'
Saat men-debug skrip shell (Bash), akan masuk akal dan waras - bahkan perlu - untuk menggunakan shell yang bernama di baris shebang dengan -xopsi. Jika tidak, Anda mungkin (akan?) Mendapatkan perilaku berbeda saat debug dari saat menjalankan skrip.
bashskrip. Dan menjalankan skrip bash dengan sh -xakan menyebabkannya berperilaku sangat berbeda! Harap perbarui jawaban Anda.
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
Saya telah menggunakan metode berikut untuk men-debug skrip saya.
set -emembuat skrip berhenti segera jika ada program eksternal mengembalikan status keluar tidak nol. Ini berguna jika skrip Anda mencoba menangani semua kasus kesalahan dan di mana kegagalan untuk melakukannya harus dijebak.
set -x disebutkan di atas dan tentunya yang paling berguna dari semua metode debugging.
set -n mungkin juga berguna jika Anda ingin memeriksa skrip Anda untuk kesalahan sintaks.
stracejuga berguna untuk melihat apa yang terjadi. Sangat berguna jika Anda belum menulis skrip sendiri.
strace -fdiperlukan jika Anda juga ingin menemukan kesalahan dalam proses yang dimulai oleh skrip. (yang membuatnya berkali-kali lebih bertele-tele, tetapi tetap berguna jika Anda membatasinya pada syscalls yang Anda minati).
set -eadalah ... kontroversial .
Jawaban ini valid dan bermanfaat: https://stackoverflow.com/a/951352
Tapi, saya menemukan bahwa metode debugging skrip "standar" tidak efisien, tidak intuitif, dan sulit digunakan. Bagi mereka yang terbiasa dengan debuggers GUI canggih yang meletakkan segalanya di ujung jari Anda dan menjadikan pekerjaan itu mudah untuk masalah yang mudah (dan mungkin untuk masalah yang sulit), solusi ini tidak terlalu memuaskan.
Apa yang saya lakukan adalah menggunakan kombinasi DDD dan bashdb. Yang pertama mengeksekusi yang terakhir, dan yang kedua mengeksekusi skrip Anda. Ini memberikan UI multi-jendela dengan kemampuan untuk melangkah melalui kode dalam konteks dan melihat variabel, tumpukan, dll., Tanpa upaya mental terus-menerus untuk mempertahankan konteks di kepala Anda atau tetap mendaftar ulang sumbernya.
Ada panduan tentang pengaturan di sini: http://ubuntuforums.org/showthread.php?t=660223
Anda juga dapat menulis "set -x" di dalam skrip.
Saya menemukan utilitas shellcheck dan mungkin beberapa orang menganggapnya menarik https://github.com/koalaman/shellcheck
Sedikit contoh:
$ cat test.sh
ARRAY=("hello there" world)
for x in $ARRAY; do
echo $x
done
$ shellcheck test.sh
In test.sh line 3:
for x in $ARRAY; do
^-- SC2128: Expanding an array without an index only gives the first element.
perbaiki bug, coba dulu ...
$ cat test.sh
ARRAY=("hello there" world)
for x in ${ARRAY[@]}; do
echo $x
done
$ shellcheck test.sh
In test.sh line 3:
for x in ${ARRAY[@]}; do
^-- SC2068: Double quote array expansions, otherwise they're like $* and break on spaces.
Mari kita coba lagi...
$ cat test.sh
ARRAY=("hello there" world)
for x in "${ARRAY[@]}"; do
echo $x
done
$ shellcheck test.sh
Cari sekarang!
Itu hanya contoh kecil.
Gunakan gerhana dengan plugin shelled & basheclipse.
https://sourceforge.net/projects/shelled/?source=directory https://sourceforge.net/projects/basheclipse/?source=directory
Untuk dikupas: Unduh zip dan impor ke gerhana melalui bantuan -> instal perangkat lunak baru: arsip lokal Untuk basheclipse: Salin guci ke direktori dropins gerhana
Ikuti langkah-langkahnya, berikan https://sourceforge.net/projects/basheclipse/files/?source=navbar
Saya menulis tutorial dengan banyak tangkapan layar di http://dietrichschroff.blogspot.de/2017/07/bash-enabling-eclipse-for-bash.html
Saya membangun debugger Bash. Cobalah saja. Saya harap ini akan membantu https://sourceforge.net/projects/bashdebugingbash
atur + x = @ECHO OFF, atur -x = @ECHO ON.
Anda dapat menambahkan -xvopsi ke Shebang standar sebagai berikut:
#!/bin/bash -xv
-x: Tampilkan perintah dan argumennya saat dieksekusi.
-v: Tampilkan baris input shell saat dibaca.
ltraceLinux Utility serupa dengan strace. Namun, ltracedaftar semua panggilan perpustakaan yang dipanggil dalam proses yang dapat dieksekusi atau berjalan. Namanya sendiri berasal dari penelusuran pustaka panggilan. Sebagai contoh:
ltrace ./executable <parameters>
ltrace -p <PID>
Saya pikir Anda dapat mencoba debugger Bash ini: http://bashdb.sourceforge.net/ .
set -[nvx]Sebagai tambahannya
set -x
dan
set +x
untuk menghentikan dump.
Saya ingin berbicara tentang set -vdump yang lebih kecil daripada output yang kurang berkembang.
bash <<<$'set -x\nfor i in {0..9};do\n\techo $i\n\tdone\nset +x' 2>&1 >/dev/null|wc -l
21
for arg in x v n nx nv nvx;do echo "- opts: $arg"
bash 2> >(wc -l|sed s/^/stderr:/) > >(wc -l|sed s/^/stdout:/) <<eof
set -$arg
for i in {0..9};do
echo $i
done
set +$arg
echo Done.
eof
sleep .02
done
- opts: x
stdout:11
stderr:21
- opts: v
stdout:11
stderr:4
- opts: n
stdout:0
stderr:0
- opts: nx
stdout:0
stderr:0
- opts: nv
stdout:0
stderr:5
- opts: nvx
stdout:0
stderr:5
Untuk menguji beberapa variabel, saya menggunakan ini:
bash <(sed '18ideclare >&2 -p var1 var2' myscript.sh) args
untuk menambahkan:
declare >&2 -p var1 var2
pada baris 18 dan menjalankan skrip yang dihasilkan (dengan args ), tanpa harus mengeditnya.
tentu saja, ini dapat digunakan untuk menambahkan set [+-][nvx]:
bash <(sed '18s/$/\ndeclare -p v1 v2 >\&2/;22s/^/set -x\n/;26s/^/set +x\n/' myscript) args
akan menambahkan declare -p v1 v2 >&2setelah baris 18, set -xsebelum baris 22 dan set +xsebelum baris 26.
bash <(sed '2,3s/$/\ndeclare -p LINENO i v2 >\&2/;5s/^/set -x\n/;7s/^/set +x\n/' <(
seq -f 'echo $@, $((i=%g))' 1 8)) arg1 arg2
arg1 arg2, 1
arg1 arg2, 2
declare -i LINENO="3"
declare -- i="2"
/dev/fd/63: line 3: declare: v2: not found
arg1 arg2, 3
declare -i LINENO="5"
declare -- i="3"
/dev/fd/63: line 5: declare: v2: not found
arg1 arg2, 4
+ echo arg1 arg2, 5
arg1 arg2, 5
+ echo arg1 arg2, 6
arg1 arg2, 6
+ set +x
arg1 arg2, 7
arg1 arg2, 8
Catatan: Perhatian $LINENOakan terpengaruh oleh modifikasi on-the-fly !
(Untuk melihat skrip yang dihasilkan tanpa menjalankan, cukup jatuhkan bash <(dan ) arg1 arg2)
Ada sejumlah detail yang bagus tentang pendataan untuk skrip shell melalui varaibles global shell. Kita dapat meniru jenis yang sama dari logging di skrip shell: http://www.cubicrace.com/2016/03/log-tracing-mechnism-for-shell-scripts.html
Posting memiliki detail tentang memperkenalkan level log seperti INFO, DEBUG, ERROR. Menelusuri detail seperti entri skrip, keluar skrip, entri fungsi, keluar fungsi.
Contoh log: