Como verificar qual linha de um script bash está sendo executada

14

Existe uma maneira de verificar qual linha número de um script bash está sendo executado "agora"?

    
por user224371 04.04.2017 / 23:16

5 respostas

20

Combine xtrace com PS4 dentro do script:

$ 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

ou no shell pai :

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

Sim, existe um caminho.
Existe uma matriz de números de linha onde uma função foi chamada.

Defina esta função:

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

E chame f em qualquer linha que você deseja que o número da linha, por exemplo:

#!/bin/bash


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

f

echo next1
f

echo next2
f

echo next 3
f

imprimirá:

6
next 1
9
next 2
12
next 3
15

Poderia ser expandido para mostrar o rastro de funções chamadas:

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

Que imprimirá:

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

Observe que acima da saída echo "$LINENO" é sempre a mesma coisa (7 neste caso).

    
por 05.04.2017 / 04:01
6

Você pode echo $LINENO em um script e deve gerar qualquer linha em que o comando esteja.

#!/bin/bash
echo $LINENO

$ ./foo.sh
2
    
por 04.04.2017 / 23:33
6

Aqui está uma solução que empresta partes de l0b0's e As respostas do DopeGhoti (e, em menor grau, sorontar ). Como essas respostas, o meu usa $LINENO para descobrir o número da linha; Diferentemente deles, eu uso trap para acionar o relatório. O comando trap do bash é descrito em bash (1) :

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

    The command arg is to be read and executed when the shell receives signal(s) sigspec.  … ⁠     ︙
    …  If a sigspec is DEBUG, the command arg is executed before every simple command, for command, case command, select command, every arithmetic for command, and before the first command executes in a shell function …

Este script:

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

executa o comando printf "%3d: " "$LINENO" antes de cada comando no script e produz esta saída:

$ ./myscript
  3: Wed, Apr 05, 2017 10:16:17 AM
  4:   5: Wed, Apr 05, 2017 10:16:47 AM
  7:   8: Wed, Apr 05, 2017 10:16:58 AM
 10: total 4
-rwxr-xr-x 1 myusername mygroup 221 Apr  5 10:01 myscript
-rwxr-xr-x 1 myusername mygroup 252 Apr  5 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: myscript
 14: -rwxr-xr-x 1 myusername mygroup 221 Apr  5 10:01 myscript
 11:  13: myscript2
 14: -rwxr-xr-x 1 myusername mygroup 252 Apr  5 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: Wed, Apr 05, 2017 10:16:59 AM
 17:  17:  19: i = 1
 19: Wed, Apr 05, 2017 10:16:59 AM
 17:  17:  19: i = 2
 19: Wed, Apr 05, 2017 10:16:59 AM
 17:  17:  22: 42
$

Notas:

  • Como a resposta do l0b0 , isso é minimamente invasivo - basta adicionar a linha 2.
  • Ao contrário da resposta do l0b0 , isso não exibe os comandos em si mas você não pediu para fazer isso.
  • O segundo sleep , que abrange as linhas de script 6 e 7, é relatado como linha 7.
  • A linha 11 ( for f in * ) é relatada uma vez antes de cada iteração desse loop for .
  • echo "$f" e ls -ld "$f" são relatados corretamente em suas respectivas linhas (13 e 14).
  • A linha 17 ( for ((i=0; i<3; i++)) ) é informada duas vezes antes de cada iteração desse loop for , e mais duas vezes após a última iteração.
  • Ao contrário de set -x , LINENO e PS4 (que são especificados pelo padrão POSIX), o DEBUG trap é uma extensão bash e não funcionará em todos os shells.
  • O DEBUG trap pode executar qualquer comando, e não se restringe a escrever na saída padrão do script ou erro padrão.

A pergunta diz: «verifique qual número de linha de um script bash está sendo executado “agora mesmo” sem especificar uma interface de usuário. Outra abordagem é escrever continuamente o número da linha atual para um arquivo de log:

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

Podemos monitorar a execução desse script monitorando o conteúdo do arquivo myscript2.log de outro terminal. Por exemplo, durante o segundo sleep ,

$ tail myscript2.log
  3
  4
  5
  7
    
por 05.04.2017 / 13:00
-1
#!/bin/bash -x

Adicione esse "-x" no início do seu script. Então, toda vez que você executar o script, ele repetirá a linha que seu script está executando. como uma árvore de execução do seu script.

    
por 05.04.2017 / 01:17