Cara memeriksa baris skrip bash yang sedang dieksekusi

15

Apakah ada cara untuk memeriksa garis jumlah dari bashnaskah yang sedang dijalankan "sekarang"?

Menggunakan bash -x script.shpenampilan yang menjanjikan; namun, saya perlu mendapatkan nomor baris saat ini.

pengguna224371
sumber

Jawaban:

20

Gabungkan xtracedengan PS4di dalam skrip:

$ cat test.sh 
#!/usr/bin/env bash
set -x
PS4='+${LINENO}: '

sleep 1m
sleep 1d
$ timeout 5 ./test.sh
+3: PS4='+${LINENO}: '
+5: sleep 1m

atau di shell induk :

$ cat test.sh 
sleep 1m
sleep 1d
$ export PS4='+${LINENO}: '
$ timeout 5 bash -x ./test.sh
+1: sleep 1m
l0b0
sumber
10

Ya ada jalan.
Ada array nomor baris di mana fungsi telah dipanggil.

Tentukan fungsi ini:

f(){ echo "${BASH_LINENO[-2]}"; }

Dan hubungi fsaluran apa pun yang Anda inginkan nomor salurannya, misalnya:

#!/bin/bash


f(){ echo "${BASH_LINENO[-2]}"; }

f

echo next1
f

echo next2
f

echo next 3
f

Akan dicetak:

6
next 1
9
next 2
12
next 3
15

Itu dapat diperluas untuk menunjukkan jejak fungsi yang disebut:

#!/bin/bash

f(){
    for ((i=${#BASH_LINENO[@]}-1;i>=0;i--)); do
    printf '<%s:%s> ' "${FUNCNAME[i]}" "${BASH_LINENO[i]}";
    done
    echo "$LINENO"
 }

SomeOtherFunction(){ echo -n "test the line numbering:  "; f; }

f

echo next 1
echo -n "    This line numbering:  "; f
SomeOtherFunction

echo next 2
echo -n "    This line numbering:  "; f
SomeOtherFunction

echo next 3
echo -n "    This line numbering:  "; f

Yang akan dicetak:

$ ./script
<main:0> <f:12> 7
next 1
    This line numbering:  <main:0> <f:15> 7
test the line numbering:  <main:0> <SomeOtherFunction:16> <f:10> 7
next 2
    This line numbering:  <main:0> <f:19> 7
test the line numbering:  <main:0> <SomeOtherFunction:20> <f:10> 7
next 3
    This line numbering:  <main:0> <f:23> 7

Perhatikan bahwa echo "$LINENO"output di atas selalu sama (7 dalam kasus ini).

sorontar
sumber
7

Berikut adalah solusi yang meminjam bagian dari l0b0 ini dan DopeGhoti ini jawaban (dan, pada tingkat lebih rendah, sorontar ini ). Seperti jawaban itu, milikku digunakan $LINENOuntuk menemukan nomor baris; tidak seperti mereka, saya gunakan trapuntuk memicu pelaporan. trapPerintah bash dijelaskan dalam bash (1) :

trap [-lp] [[arg] sigspec ...]

    Argumen perintah harus dibaca dan dieksekusi ketika shell menerima sinyal sigspec . ... ⁠ ︙
    ... Jika SIGSPEC adalah DEBUG , perintah arg dijalankan sebelum setiap perintah sederhana , forperintah, caseperintah, selectperintah, setiap aritmatika forperintah, dan sebelum mengeksekusi perintah pertama dalam fungsi shell ...

Jadi skrip ini:

$ cat -n myscript
     1  #!/bin/bash
     2  trap 'printf "%3d: " "$LINENO"' DEBUG
     3  date
     4  sleep 30
     5  date
     6  sleep \
     7        11
     8  date
     9
    10  ls -l
    11  for f in *
    12  do
    13          echo "$f"  &&
    14                         ls -ld "$f"
    15  done
    16
    17  for ((i=0; i<3; i++))
    18  do
    19          echo "i = $i"; date
    20  done
    21
    22  echo $((5+25+12))
$

menjalankan printf "%3d: " "$LINENO"perintah sebelum setiap perintah dalam skrip, dan menghasilkan output ini:

$ ./myscript
  3: Rab, 05 Apr 2017 10:16:17 AM
  4: 5: Rabu, 05 Apr 2017 10:16:47
  7: 8: Rabu, 05 Apr 2017 10:16:58
 10: total 4
-rwxr-xr-x 1 myusername mygroup 221 Apr 5 10:01 myscript
-rwxr-xr-x 1 myusername mygroup 252 5 Apr 10:01 myscript2
-rw-r - r-- 1 myusername mygroup 132 Apr 5 09:59 myscript2.log
-rw-r - r-- 1 myusername mygroup   45 Apr 5 08:34 other_file
 11:13: naskah saya
 14: -rwxr-xr-x 1 myusername mygroup 221 Apr 5 10:01 myscript
 11:13: myscript2
 14: -rwxr-xr-x 1 myusername mygroup 252 5 Apr 10:01 myscript2
 11:13: myscript2.log
 14: -rw-r - r-- 1 myusername mygroup 132 Apr 5 09:59 myscript2.log
 11:13: other_file
 14: -rw-r - r-- 1 myusername mygroup   45 Apr 5 08:34 other_file
 17: 17: 19: i = 0
 19: Rabu, 05 Apr 2017 10:16:59 AM
 17:17: 19: i = 1
 19: Rabu, 05 Apr 2017 10:16:59 AM
 17:17: 19: i = 2
 19: Rabu, 05 Apr 2017 10:16:59 AM
 17: 17: 22: 42
$

Catatan:

  • Seperti jawaban l0b0 , ini invasif minimal - cukup tambahkan baris 2.
  • Tidak seperti jawaban l0b0 , ini tidak menampilkan perintah sendiri - tetapi Anda tidak memintanya untuk melakukan itu.
  • Yang kedua sleep, yang mencakup skrip baris 6 dan 7, dilaporkan sebagai baris 7.
  • Baris 11 ( for f in *) dilaporkan satu kali sebelum setiap iterasi dari forloop itu.
  • echo "$f"dan ls -ld "$f"dilaporkan dengan benar pada baris masing-masing (13 dan 14).
  • Baris 17 ( for ((i=0; i<3; i++))) dilaporkan dua kali sebelum setiap iterasi dari forloop itu, dan dua kali lebih banyak setelah iterasi terakhir.
  • Tidak seperti set -x, LINENOdan PS4 (yang ditentukan oleh standar POSIX), DEBUG trapadalah ekstensi bash dan tidak akan bekerja di semua shell.
  • DEBUG trapdapat menjalankan perintah apa pun, dan tidak terbatas pada penulisan ke output standar skrip atau kesalahan standar.

Pertanyaannya mengatakan, «periksa nomor baris skrip bash mana yang sedang dieksekusi" sekarang "» tanpa menentukan antarmuka pengguna. Pendekatan lain adalah terus menulis nomor baris saat ini ke file log:

$ diff myscript myscript2
2c2
<trap 'printf "% 3d:" "$ LINENO"' DEBUG
---
> exec 6> myscript2.log && trap 'printf "% 3d \ n" "$ LINENO"> & 6' DEBUG
$ ./myscript2
Rabu, 05 Apr 2017 10:23:50
Rabu, 05 Apr 2017 10:24:20 pagi
Rabu, 05 Apr 2017 10:24:31 AM
total 4
-rwxr-xr-x 1 myusername mygroup 221 Apr 5 10:01 myscript
-rwxr-xr-x 1 myusername mygroup 252 5 Apr 10:01 myscript2
-rw-r - r-- 1 myusername mygroup   24 Apr 5 10:23 myscript2.log
-rw-r - r-- 1 myusername mygroup   45 Apr 5 08:34 other_file
skrip saya
-rwxr-xr-x 1 myusername mygroup 221 Apr 5 10:01 myscript
myscript2
-rwxr-xr-x 1 myusername mygroup 252 5 Apr 10:01 myscript2
myscript2.log
-rw-r - r-- 1 myusername mygroup   60 Apr 5 10:23 myscript2.log
file_lainnya
-rw-r - r-- 1 myusername mygroup   45 Apr 5 08:34 other_file
i = 0
Rabu, 05 Apr 2017 10:24:31 AM
i = 1
Rabu, 05 Apr 2017 10:24:31 AM
i = 2
Rabu, 05 Apr 2017 10:24:31 AM
42
$

Kami dapat memantau pelaksanaan skrip ini dengan memonitor konten myscript2.logfile dari terminal lain. Misalnya, selama detik sleep,

$ tail myscript2.log
  3
  4
  5
  7
G-Man Mengatakan 'Reinstate Monica'
sumber
6

Anda bisa echo $LINENOdalam skrip dan harus menampilkan baris apa pun yang perintahnya berada.

#!/bin/bash
echo $LINENO

$ ./foo.sh
2
DopeGhoti
sumber
-1
#!/bin/bash -x

Tambahkan "-x" di awal skrip Anda. Kemudian setiap kali Anda mengeksekusi skrip itu akan menggemakan baris skrip Anda dieksekusi. seperti pohon eksekusi skrip Anda.

Pavan Shah
sumber
4
OP telah menolak saran ini sebagai tidak memuaskan.
G-Man Mengatakan 'Reinstate Monica'