Cara menampilkan nomor baris saat menjalankan skrip bash

89

Saya memiliki skrip uji yang memiliki banyak perintah dan akan menghasilkan banyak keluaran, saya menggunakan set -xatau set -vdan set -e, sehingga skrip akan berhenti ketika terjadi kesalahan. Namun, masih agak sulit bagi saya untuk menemukan jalur mana yang menghentikan eksekusi untuk menemukan masalahnya. Apakah ada metode yang dapat menampilkan nomor baris skrip sebelum setiap baris dieksekusi? Atau keluaran nomor baris sebelum pameran perintah dibuat oleh set -x? Atau metode apa pun yang dapat menangani masalah lokasi baris skrip saya akan sangat membantu. Terima kasih.

dspjm.dll
sumber

Jawaban:

161

Anda menyebutkan bahwa Anda sudah menggunakan -x. Variabel PS4menunjukkan nilainya adalah prompt yang dicetak sebelum baris perintah digaungkan ketika -xopsi disetel dan defaultnya :diikuti oleh spasi.

Anda dapat mengubah PS4untuk mengeluarkan LINENO(Nomor baris dalam skrip atau fungsi shell yang sedang dijalankan).

Misalnya, jika skrip Anda berbunyi:

$ cat script
foo=10
echo ${foo}
echo $((2 + 2))

Dengan menjalankannya maka akan mencetak nomor baris:

$ PS4='Line ${LINENO}: ' bash -x script
Line 1: foo=10
Line 2: echo 10
10
Line 3: echo 4
4

http://wiki.bash-hackers.org/scripting/debuggingtips memberikan hasil akhir PS4yang akan menampilkan semua yang mungkin Anda perlukan untuk penelusuran:

export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
devnull
sumber
4
Saya bertanya-tanya mengapa tidak ada yang menyebutkan ini untuk "Bagaimana cara men-debug skrip shell?" . Ini jauh lebih baik daripada hanyaecho
Suvarna Pattayil
@VusP Setuju, echosebaiknya hindari pernyataan yang tidak perlu .
devnull
2
Saya tidak bisa membantu tetapi merasa itu -x harus mencetak nomor baris. Atau, mungkin - nx harus menyertakan nomor baris. Bagi saya, ini salah satu momen "WTF" ...
jww
1
Sobat, saya berharap saya tahu tentang ramuan PS4 itu lebih cepat ... Itu akan menyelamatkan saya begitu banyak sakit kepala
niken
2
\033[0;33m+(${BASH_SOURCE}:${LINENO}):\033[0m ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'untuk beberapa warna
Ulysse BN
35

Di Bash, $LINENOberisi nomor baris tempat skrip sedang dieksekusi.

Jika Anda perlu mengetahui nomor baris tempat fungsi itu dipanggil, coba $BASH_LINENO. Perhatikan bahwa variabel ini adalah array.

Sebagai contoh:

#!/bin/bash       

function log() {
    echo "LINENO: ${LINENO}"
    echo "BASH_LINENO: ${BASH_LINENO[*]}"
}

function foo() {
    log "$@"
}

foo "$@"

Lihat di sini untuk detail variabel Bash.

Deqing
sumber
0

Solusi sederhana (tapi kuat): Letakkan di echosekitar kode yang menurut Anda menyebabkan masalah dan pindahkan echobaris demi baris hingga pesan tidak muncul lagi di layar - karena skrip telah berhenti karena kesalahan sebelumnya.

Solusi yang lebih kuat: Instal bashdbdebugger bash dan debug skrip baris demi baris

hek2mgl
sumber
2
echomempelajari sesuatu dapat membantu dalam banyak kasus, tetapi gagal saat Anda mencoba menerapkannya dalam fungsi yang memiliki keluaran yang bermakna dan dapat diurai.
Eliran Malka
1
@Liran_cinta Anda dapat menggema ke stderr dalam kasus ini:echo "foo" >&2
hek2mgl
1
... seseorang harus bergema ke stderr dalam semua kasus jika tujuannya adalah pesan yang bersifat diagnostik.
Charles Duffy
0

Solusi untuk cangkang tanpa LINENO

Dalam skrip yang cukup canggih, saya tidak ingin melihat semua nomor baris; melainkan saya ingin mengontrol output.

Tentukan fungsi

echo_line_no () {
    grep -n "$1" $0 |  sed "s/echo_line_no//" 
    # grep the line(s) containing input $1 with line numbers
    # replace the function name with nothing 
} # echo_line_no

Gunakan dengan tanda kutip seperti

echo_line_no "this is a simple comment with a line number"

Outputnya adalah

16   "this is a simple comment with a line number"

jika jumlah baris ini di file sumber adalah 16.

Ini pada dasarnya menjawab pertanyaan Bagaimana cara menampilkan nomor baris saat menjalankan skrip bash untuk pengguna ash atau shell lain tanpa LINENO.

Ada lagi yang ingin ditambahkan?

Tentu. Mengapa Anda membutuhkan ini? Bagaimana Anda bekerja dengan ini? Apa yang dapat Anda lakukan dengan ini? Apakah pendekatan sederhana ini benar-benar cukup atau berguna? Mengapa Anda ingin mengotak-atik ini?

Ingin tahu lebih banyak? Baca refleksi tentang debugging

kklepper.dll
sumber