Bagaimana cara debug skrip bash?

135

Saya mengalami beberapa masalah dengan beberapa skrip di bash, tentang kesalahan dan perilaku yang tidak terduga. Saya ingin menyelidiki penyebab masalah sehingga saya dapat menerapkan perbaikan. Apakah ada cara saya dapat mengubah semacam "mode debug" untuk bash, untuk mendapatkan informasi lebih lanjut?

Braiam
sumber

Jawaban:

132

Mulai skrip bash Anda dengan bash -x ./script.shatau tambahkan skrip Anda set -xuntuk melihat hasil debug.


Tambahan dengan bash4.1 atau lebih baru:

Jika Anda ingin menulis hasil debug ke file terpisah, tambahkan ini ke skrip Anda:

exec 5> debug_output.txt
BASH_XTRACEFD="5"

Lihat: https://stackoverflow.com/a/25593226/3776858


Jika Anda ingin melihat nomor baris, tambahkan ini:

PS4='$LINENO: '


Jika Anda memiliki akses ke loggerperintah maka Anda dapat menggunakannya untuk menulis keluaran debug melalui syslog Anda dengan stempel waktu, nama skrip, dan nomor baris:

#!/bin/bash

exec 5> >(logger -t $0)
BASH_XTRACEFD="5"
PS4='$LINENO: '
set -x

# Place your code here

Anda dapat menggunakan opsi -pdari loggerperintah untuk mengatur fasilitas individu dan tingkat untuk menulis output melalui syslog lokal untuk logfile sendiri.

Cyrus
sumber
7
-v juga dapat membantu (mencetak setiap baris saat dieksekusi. dapat dikombinasikan dengan -x). Dan lihat juga: bashdb.sourceforge.net
Olivier Dulac
4
Sumber lain yang luar biasa adalah: shellcheck.net
Olivier Dulac
Apa yang dilakukan "exec 5>"?
aggsol
3
@aggsol: Jika Anda menggunakan BASH_XTRACEFD="5"bash, tulis jejak keluaran yang dihasilkan saat set -xdiaktifkan ke file descriptor 5. exec 5> >(logger -t $0)redirect output dari file descriptor 5 ke loggerperintah.
Cyrus
1
Hanya ingin tahu, bisakah Anda mendapatkan nomor atau jalur skrip shell atau nama di PS4?
iloveretards
55

Menggunakan set -x

Saya selalu menggunakan set -xdan set +x. Anda dapat membungkus area yang ingin Anda lihat apa yang terjadi dengan mereka untuk menaikkan / menurunkan verbositas.

#!/bin/bash

set -x
..code to debug...
set +x

log4bash

Juga jika Anda telah melakukan pekerjaan pengembangan dan terbiasa dengan gaya logger yang menggunakan nama log4j, log4perl, dll., Maka Anda mungkin ingin menggunakan log4bash .

kutipan

Mari kita hadapi itu - gema tua polos tidak memotongnya. log4bash adalah upaya untuk memiliki pendataan yang lebih baik untuk skrip Bash (yaitu membuat penebangan di Bash kurang menyedot).

Dari sana Anda dapat melakukan hal-hal seperti ini di skrip Bash Anda:

#!/usr/bin/env bash
source log4bash.sh

log "This is regular log message... log and log_info do the same thing";

log_warning "Luke ... you turned off your targeting computer";
log_info "I have you now!";
log_success "You're all clear kid, now let's blow this thing and go home.";
log_error "One thing's for sure, we're all gonna be a lot thinner.";

# If you have figlet installed -- you'll see some big letters on the screen!
log_captains "What was in the captain's toilet?";

# If you have the "say" command (e.g. on a Mac)
log_speak "Resistance is futile";

Menghasilkan jenis output ini:

    ss1

log4sh

Jika Anda membutuhkan sesuatu yang lebih portabel ada juga yang lebih tua log4sh. Pekerjaan serupa dengan log4bash, tersedia di sini:

slm
sumber
Di Ubuntu, saya punya alias say="spd-say"di .bashrc saya, yang meniru sayperintah dari distro lain atau OS X.
Doorknob
1
set -vx akan menjadi kombinasi yang bagus jika digunakan dengan trap - trap read debug. Ini memungkinkan Anda untuk melangkahi baris demi baris dan melihat hasilnya
Magnus Melwin
34

Ada bash debugger, bashdb , yang merupakan paket yang dapat diinstal pada banyak distro. Ini menggunakan mode debugging diperpanjang bawaan bash ( shopt -s extdebug). Ini mirip sekali dengan gdb; inilah sesi contoh untuk memberikan rasa:

$ ls
1st.JPG  2ndJPG.JPG
$ cat ../foo.sh
for f in *.JPG
do
  newf=${f/JPG/jpg}
  mv $f $newf
done
$ bashdb ../foo.sh
(foo.sh:1):
1:      for f in *.JPG
bashdb<0> next
(foo.sh:3):
3:        newf=${f/JPG/jpg}
bashdb<1> next
(foo.sh:4):
4:        mv $f $newf

Seperti dalam gdb, pernyataan ditampilkan tepat sebelum akan dieksekusi. Jadi kita bisa memeriksa variabel untuk melihat apa yang akan dilakukan pernyataan sebelum melakukannya.

bashdb<2> print $f $newf
1st.JPG 1st.jpg
bashdb<3> next
(foo.sh:1):
1:      for f in *.JPG
bashdb<4> next
(foo.sh:3):
3:        newf=${f/JPG/jpg}
bashdb<5> next
(foo.sh:4):
4:        mv $f $newf
bashdb<6> print $f $newf
2ndJPG.JPG 2ndjpg.JPG

Bukan itu yang kita inginkan! Mari kita lihat lagi ekspansi parameter.

bashdb<7> print $f ${f/JPG/jpg}
2ndJPG.JPG 2ndjpg.JPG
bashdb<8> print $f ${f/JPG$/jpg}
2ndJPG.JPG 2ndJPG.JPG
bashdb<9> print $f ${f/%JPG/jpg}
2ndJPG.JPG 2ndJPG.jpg

Oke, itu berhasil. Mari kita atur newfke nilai yang benar.

bashdb<10> eval newf=${f/%JPG/jpg}
$? is 0
bashdb<11> print $f $newf
2ndJPG.JPG 2ndJPG.jpg

Kelihatan bagus. Lanjutkan skrip.

bashdb<12> next
Debugged program terminated normally. Use q to quit or R to restart.
$ ls
1st.jpg  2ndJPG.jpg
Tandai Plotnick
sumber
20

Metode standar untuk men-debug skrip di sebagian besar shell berbasis Bourne, seperti bash adalah menulis set -xdi bagian atas skrip Anda. Ini akan membuat bash lebih banyak bicara tentang apa yang sedang dilakukan / dieksekusi, dan bagaimana argumen dievaluasi.

-x  Print commands and their arguments as they are executed.

ini berguna untuk skrip interpreter atau skrip dalam. Sebagai contoh:

$ find "$fileloc" -type f -prune "$filename" -print
+ find /var/adm/logs/morelogs -type f -prune '-name *.user' -print
find: unknown predicate '-name *.user'
$ find "$fileloc" -type f -prune $filename -print
+ find /var/adm/logs/morelogs -type f -prune -name '*.user' -print
find: '/var/adm/logs/morelogs': No such file or directory

Di atas kita bisa melihat mengapa find gagal karena beberapa kutipan tunggal.

Untuk menonaktifkan fitur, cukup ketik set +x.

Braiam
sumber
13

Menggunakan Eclipse

Anda dapat menggunakan lingkungan gabungan Eclipse dan Shelled dengan skrip "_DEBUG.sh" yang ditautkan di bawah ini.

Mengganti cangkang

Secara default alat pengembangan Shelled menggunakan /bin/dashsebagai penerjemah. Saya mengubah ini agar /bin/bashmemiliki kompatibilitas yang lebih baik dengan sebagian besar contoh shell di web dan lingkungan saya.

CATATAN: Anda dapat mengubah ini dengan masuk ke: Jendela -> Preferensi -> Skrip Shell -> Penerjemah

Petunjuk Penyiapan

Paket Debugger memiliki langkah-langkah untuk menggunakan _DEBUG.shskrip untuk debugging skrip Anda yang pada dasarnya (readme.txt):

  1. Buat Shell Script Project: File -> New -> Other -> Shell Script -> Shell Script Project Wizard .
  2. Buat file skrip Bash: File -> Baru -> File . Untuk contoh ini, itu akan menjadi script.sh. Ekstensi harus ".sh" dan merupakan keharusan.
  3. Salin file _DEBUG.shke folder proyek.
  4. Masukkan teks berikut ke bagian atas file script.sh:

    . _DEBUG.sh
  5. Jika file dibuat di Microsoft Windows maka pastikan untuk mengeksekusi File -> Convert Line Delimiters To -> Unix .

  6. Menyiapkan konfigurasi peluncuran debug: Jalankan -> Konfigurasi Debug -> Skrip Bash ... Ada 2 bidang untuk disetel di sini:

    a) "Bash script:" - Path di ruang kerja Eclipse ke skrip Bash untuk debug.
    e) "Debugger port:" 33333

  7. Beralih ke perspektif Debug. Mulai sesi debugging. Luncurkan script.shdari bash shell.

UI debug bash

masukkan deskripsi gambar di sini

Bash debugger ini memiliki fitur lengkap dari debugger pemrograman standar seperti:

  • Matikan Point toggle
  • Operasi langkah demi langkah tunggal
  • Step-in, Step-out, fungsi Step-over dan sub-rutin
  • Memeriksa kode atau variabel di titik mana pun saat skrip berjalan

IDE Shelled (Shell Script Editor) (Lingkungan Pengembangan Terpadu) memiliki bonus tambahan untuk melakukan pengecekan konteks, penyorotan dan indentasi saat menulis skrip Anda. Jika tidak indentasi dengan benar, Anda mungkin dapat langsung menandai / lokal banyak kesalahan di sana.

Lalu ada manfaat IDE lainnya seperti:

  • Daftar tugas TODO
  • Tugas Mylyn
  • Daftar bookmark
  • Pengeditan Banyak Jendela
  • Berbagi jarak jauh dari lingkungan
LD James
sumber
Kiat keren. Senang mengetahui bahwa Bash dapat ditipu seperti ini.
slm
8

Sumber yang luar biasa muncul dalam beberapa tahun terakhir: http://shellcheck.net

itu menunjukkan Anda lebih daripada bash biasa, memungkinkan seseorang untuk menemukan dengan mudah kutipan yang tidak tertutup atau kurung keriting, dll.

Pastikan Anda tidak menempelkan info sensitif (ips, kata sandi, dll) di internet ... (terutama karena http, tidak terenkripsi) (Saya percaya shellcheck juga tersedia untuk diunduh, tetapi saya tidak yakin)

Olivier Dulac
sumber
6

cukup gunakan:

#!/bin/bash -x

sama untuk shell:

#!/bin/sh -x
Gery
sumber
6

Saat ini, ada VS Code Bash Debug.

https://marketplace.visualstudio.com/items?itemName=rogalmic.bash-debug

Ini memiliki 'Langkah Masuk / Keluar / Lebih' dan juga menunjukkan nilai dari setiap variabel.

Tangkapan layar VS Code Bash Debug

Henrique Lemos Ribeiro
sumber
jawaban ini tidak menjawab pertanyaan dalam konteks yang benar; mengasumsikan baris perintah sejak IDE tidak disebutkan
qodeninja