Bagaimana cara debug skrip bash? [Tutup]

159

Apakah ada cara untuk men-debug skrip bash? Misalnya sesuatu yang mencetak semacam log eksekusi seperti "saluran telepon 1", "saluran telepon 2" dll.

corvus
sumber
2
Ada pertanyaan serupa di sini: serverfault.com/questions/16204/…
Dijeda hingga pemberitahuan lebih lanjut.

Jawaban:

195
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.

Jonathan Leffler
sumber
1
Dia memang menentukan bashskrip. Dan menjalankan skrip bash dengan sh -xakan menyebabkannya berperilaku sangat berbeda! Harap perbarui jawaban Anda.
lhunath
1
@ lhunath: Dengan cara apa 'sh -x' (atau 'bash -x') membuat skrip berperilaku sangat berbeda? Jelas, ini menghasilkan informasi jejak ke stderr; itu diberikan (meskipun tidak disebutkan dalam jawaban saya). Tapi apa lagi? Saya menggunakan 'bash' sebagai 'sh' di Linux dan MacOS X dan belum melihat masalah serius.
Jonathan Leffler
6
Ada perbedaan, di startup dan di bawah runtime. Mereka sepenuhnya didokumentasikan dalam distribusi Bash.
TheBonsai
4
Berikut tautan ke bash doc: gnu.org/software/bash/manual/bashref.html#Bash-Startup-Files 'Jika Bash dipanggil dengan nama sh, ia mencoba meniru perilaku startup versi historis sh sebagai semirip mungkin, sementara menyesuaikan dengan standar
posix
6
Dan gunakan prompt PS4 untuk memberikan informasi yang lebih bermanfaat seperti: export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
estani
28

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.


sumber
1
Stracing skrip (yaitu stracing shell yang menjalankan skrip) adalah metode debug shell yang aneh (tetapi mungkin bekerja untuk sejumlah masalah terbatas).
TheBonsai
1
Saya akui itu aneh dan juga sangat bertele-tele, tetapi jika Anda membatasi output strace ke beberapa syscalls, itu menjadi berguna.
1
Catatan yang 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).
Random832
set -eadalah ... kontroversial .
Charles Duffy
12

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

Stabledog
sumber
Baru ditemukan ddd berkat jawaban Anda. Di Ubuntu 12.04.3 (64bit), versi apt-sources tidak berfungsi. Saya harus mengkompilasi & menginstal dari sumber untuk mulai men-debug skrip bash saya. Petunjuk di sini - askubuntu.com/questions/156906/… membantu.
chronodekar
Ya, itu masalah. Saya menyelesaikannya beberapa waktu lalu dengan beberapa skrip - 'dddbash' menginstal / membangun DDD, menghapus versi lama jika salah, menginstal bashdb, dll. (Jawaban telah diedit dengan info ini sekarang)
Stabledog
10

Anda juga dapat menulis "set -x" di dalam skrip.

Cheeto
sumber
4
Dan Anda dapat menulis 'set + x' untuk mematikannya.
Jonathan Leffler
10

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.

Pemecah Persamaan
sumber
1
Dan ini online !
Nick Westgate
Untungnya alat ini telah berevolusi ke titik di mana ia juga menemukan bug yang tersisa.
tripleee
3

Instal VSCode , lalu tambahkan ekstensi bash debug dan Anda siap melakukan debug dalam mode visual. lihat di sini dalam aksi.

masukkan deskripsi gambar di sini

yantaq
sumber
3

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

masukkan deskripsi gambar di sini

Saya menulis tutorial dengan banyak tangkapan layar di http://dietrichschroff.blogspot.de/2017/07/bash-enabling-eclipse-for-bash.html

Dietrich Schroff
sumber
2
Ini adalah jawaban untuk tautan saja (juga lihat di sini ). Anda harus memperluas jawaban Anda untuk memasukkan sebanyak mungkin informasi di sini, setidaknya minimum yang diperlukan untuk benar-benar mencapai apa yang Anda sarankan, dan gunakan tautan hanya untuk referensi. Pada dasarnya, posting di Stack Overflow (dan semua Stack Exchange) harus lengkap. Itu berarti bahwa informasi yang cukup harus ada dalam jawaban Anda sehingga pembaca tidak perlu pergi ke luar untuk petunjuk. Saat ini, bukan itu yang terjadi untuk jawaban ini.
Makyen
ini adalah jawaban pertama yang saya temukan setelah melihat banyak yang benar-benar menunjukkan bahwa debugging yang sebenarnya adalah mungkin. Jawaban standar "set + x" sangat cocok dengan jawaban yang lengkap tetapi hampir dengan sengaja mengabaikan pertanyaan sebenarnya tentang debugging yang benar. Saya salut jawaban ini 👏
simbo1905
2

Saya membangun debugger Bash. Cobalah saja. Saya harap ini akan membantu https://sourceforge.net/projects/bashdebugingbash

abadjm
sumber
BDB saat ini didukung dalam bahasa Inggris dan Spanyol. Untuk mengubah bahasa, edit file / etc / default /
bdb
tangkapan layar terlihat menarik tetapi saya tidak bisa menjalankannya "bdb.sh: line 32: bdbSTR [1]: unbound variable"; btw akankah itu menunjukkan nilai saat ini dari semua variabel yang disetel setiap langkah yang kita lakukan pada kode?
Aquarius Power
2

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>  

Sumber

Premraj
sumber
1

Beberapa trik untuk debug skrip:

Menggunakan 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

Variabel dump atau penelusuran dengan cepat

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.

sampel kecil:

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)

Langkah demi langkah, waktu eksekusi

Lihat jawaban saya tentang cara memprofilkan skrip bash

F. Hauri
sumber
0

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:

masukkan deskripsi gambar di sini

Piyush Chordia
sumber