Bir bash betiğinin hangi satırının yürütüldüğünü kontrol etme


15

Bir komut dosyasının hangi satır numarasınınbash "şu anda" yürütüldüğünü kontrol etmenin bir yolu var mı ?

Kullanılması bash -x script.shumut verici görünüyor; Ancak, geçerli satır numarasını almak gerekir.

Yanıtlar:


20

Komut dosyasının içinde xtraceile birleştirin PS4:

$ 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

veya ana kabukta :

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

10

Evet, bir yolu var.
Bir işlevin çağrıldığı bir dizi satır numarası vardır.

Bu işlevi tanımlayın:

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

Ve fhat numarasını istediğiniz herhangi bir hattı arayın , örneğin:

#!/bin/bash


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

f

echo next1
f

echo next2
f

echo next 3
f

Yazdırılacak:

6
next 1
9
next 2
12
next 3
15

Adı verilen işlevlerin izini göstermek için genişletilebilir:

#!/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

Hangi yazdıracak:

$ ./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

Yukarıdaki echo "$LINENO"çıkışın her zaman aynı olduğunu unutmayın (bu durumda 7).


7

İşte l0b0 ve DopeGhoti’nin cevaplarını (ve daha az ölçüde sorontar’ları ) ödünç alan bir çözüm . Bu cevaplar gibi benimki $LINENOde satır numarasını bulmak için kullanır ; onlardan farklı olarak trap, raporlamayı tetiklemek için kullanıyorum . bash trapkomutu bash (1) ' de tanımlanmıştır :

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

    Komut arg , kabuk sigspec sinyalleri aldığında okunmalı ve yürütülmelidir . ... ⁠ ︙
    bir olursa ... sigspec olan DEBUG , komut arg her önce yürütülür basit komutla , forkomuta, casekomuta, selectkomuta, her aritmetik forkomuta ve bir kabuk işlevinde ilk komut çalışmasından önce ...

Yani bu senaryo:

$ 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))
$

printf "%3d: " "$LINENO"komutu komut dosyasındaki her komuttan önce çalıştırır ve şu çıktıyı üretir:

$ ./myscript
  3: Çar, 05 Nis 2017, 10:16:17
  04: 05: Çarş, Nis 05, 2017 10:16:47
  07: 8: Çar, 05 Nis 2017, 10:16:58
 10: toplam 4
-rwxr-xr-x 1 kullanıcı adı mygroup 221 Nisan 5 10:01 myscript
-rwxr-xr-x 1 kullanıcı adı mygroup 252 Nis 5 10:01 myscript2
-rw-r - r-- 1 myusername mygroup 132 Nis 5 09:59 myscript2.log
-rw-r - r-- 1 kullanıcı adı mygroup   45 Nis 5 08:34 other_file
 11: 13: myscript
 14: -rwxr-xr-x 1 kullanıcı adı mygroup 221 Nisan 5 10:01 myscript
 11: 13: myscript2
 14: -rwxr-xr-x 1 kullanıcı adı mygroup 252 Nisan 5 10:01 myscript2
 11: 13: myscript2.log
 14: -rw-r - r-- 1 myusername mygroup 132 Nis 5 09:59 myscript2.log
 11: 13: diğer_dosya
 14: -rw-r - r-- 1 kullanıcı adı mygroup   45 Nis 5 08:34 other_file
 17: 17: 19: i = 0
 19: Çar, 05 Nis 2017, 10:16:59
 17: 17: 19: i = 1
 19: Çar, 05 Nis 2017, 10:16:59
 17: 17: 19: i = 2
 19: Çar, 05 Nis 2017, 10:16:59
 17: 17: 22: 42
$

Notlar:

  • Gibi l0b0 cevabı sadece çizgi 2 eklemek - Bu minimal invaziv olduğunu.
  • L0b0'ın cevabından farklı olarak , bu komutların kendisini göstermez - ama bunu yapmasını istemediniz.
  • sleepKomut dosyası satır 6 ve 7'yi kapsayan ikinci satır, satır 7 olarak bildirilir.
  • Satır 11 ( for f in *), bu fordöngünün her yinelemesinden önce bir kez rapor edilir .
  • echo "$f"ve ls -ld "$f"ilgili satırlarında (13 ve 14) doğru bir şekilde rapor edilir.
  • Hat 17 ( for ((i=0; i<3; i++))) bildirilmektedir iki kez o her tekrarında önce fordöngü ve iki kez daha son yineleme sonra.
  • Ve (POSIX standardı tarafından belirtilen) aksine set -x, DEBUG bir bash uzantısıdır ve tüm kabuklarda çalışmaz.LINENOPS4trap
  • DEBUG trapherhangi bir komutu çalıştırabilir ve komut dosyasının standart çıktısına veya standart hatasına yazmakla sınırlı değildir.

Soru, bir kullanıcı arabirimi belirtmeden «bir bash betiğinin hangi satır numarasının“ şu anda yürütüldüğünü kontrol edin »» diyor. Başka bir yaklaşım, sürekli olarak geçerli satır numarasını bir günlük dosyasına yazmaktır:

$ diff myscript myscript2
2C2
<trap 'printf "% 3d:" "$ LINENO"' HATA AYIKLAMA
---
> exec 6> myscript2.log && trap 'printf "% 3d \ n" "$ LINENO"> & 6' DEBUG
$ ./myscript2
Çar, 05 Nis 2017, 10:23:50
Çar, 05 Nis 2017, 10:24:20
Çar, 05 Nis 2017, 10:24:31
toplam 4
-rwxr-xr-x 1 kullanıcı adı mygroup 221 Nisan 5 10:01 myscript
-rwxr-xr-x 1 kullanıcı adı mygroup 252 Nis 5 10:01 myscript2
-rw-r - r-- 1 myusername mygroup   24 Nis 5 10:23 myscript2.log
-rw-r - r-- 1 kullanıcı adı mygroup   45 Nis 5 08:34 other_file
myscript
-rwxr-xr-x 1 kullanıcı adı mygroup 221 Nisan 5 10:01 myscript
myscript2
-rwxr-xr-x 1 kullanıcı adı mygroup 252 Nis 5 10:01 myscript2
myscript2.log
-rw-r - r-- 1 myusername mygroup   60 Nis 5 10:23 myscript2.log
other_file
-rw-r - r-- 1 kullanıcı adı mygroup   45 Nis 5 08:34 other_file
i = 0
Çar, 05 Nis 2017, 10:24:31
i = 1
Çar, 05 Nis 2017, 10:24:31
i = 2
Çar, 05 Nis 2017, 10:24:31
42
$

myscript2.logDosyanın içeriğini başka bir terminalden izleyerek bu komut dosyasının yürütülmesini izleyebiliriz . Örneğin, ikinci sırada sleep,

$ tail myscript2.log
  3
  4
  5
  7

6

Şunları yapabilirsiniz echo $LINENOBir komut ve komut olur ne olursa olsun hat çıkışı olmak gerekir.

#!/bin/bash
echo $LINENO

$ ./foo.sh
2

-1
#!/bin/bash -x

Komut dosyanızın başına "-x" ekleyin. Daha sonra komut dosyasını her çalıştırdığınızda, komut dosyanızın yürüttüğü satırı yansıtacaktır. Senaryonuzun bir yürütme ağacı gibi.


4
OP, bu öneriyi tatmin edici olmadığı için zaten reddetmiştir.
G-Man
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.