Як перевірити, який рядок сценарію bash виконується


15

Чи є спосіб , щоб перевірити , яку лінію номер з bashсценарію виконуються «прямо зараз»?

Використання bash -x script.shвиглядає перспективно; однак мені потрібно отримати номер поточного рядка.

Відповіді:


20

Об'єднати xtraceз 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

або в батьківській оболонці :

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

10

Так, спосіб є.
Існує масив номерів рядків, де викликана функція.

Визначте цю функцію:

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

І зателефонуйте fв будь-яку лінію, на яку потрібно номер лінії, наприклад:

#!/bin/bash


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

f

echo next1
f

echo next2
f

echo next 3
f

Буде надруковано:

6
next 1
9
next 2
12
next 3
15

Його можна розширити, щоб відобразити слід функцій, званих:

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

Який надрукує:

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

Зауважте, що вище echo "$LINENO"вихід завжди однаковий (7 у цьому випадку).


7

Ось рішення, яке запозичує частини відповідей l0b0 та відповідей DopeGhoti (і, в меншій мірі, соронтар ). Як і ці відповіді, моя використовує $LINENOдля виявлення номера рядка; На відміну від них, я використовую trapдля запуску звітності. trapКоманда bash описана в bash (1) :

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

    Команда Arg повинна бути прочитана і виконана , коли оболонка приймає сигнал (и) sigspec . … ⁠ ︙
    … Якщо знаком є DEBUG , команда arg виконується перед кожною простою командою , forкомандою, caseкомандою, selectкомандою, кожною арифметичною forкомандою та перед виконанням першої команди в функції оболонки…

Отже, цей сценарій:

$ 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"команду перед кожною командою в скрипті і виробляє цей вихід:

$ ./script
  3: Ср, 05 квітня 2017 10:16:17
  4: 5: ср, 05 квітня 2017 10:16:47 ранку
  7: 8: ср, 05 квітня 2017 10:16:58
 10: всього 4
-rwxr-xr-x 1 myusername mygroup 221 5 квітня 10:01 таємниця
-rwxr-xr-x 1 myusername mygroup 252 квітня 5 10:01 myscript2
-rw-r - r-- 1 myusername mygroup 132 5 квітня 09:59 myscript2.log
-rw-r - r-- 1 myusername mygroup   45 5 квітня 08:34 other_file
 11: 13: таємниця
 14: -rwxr-xr-x 1 myusername mygroup 221 5 квітня 10:01 таємниця
 11: 13: таємниця2
 14: -rwxr-xr-x 1 myusername mygroup 252 квітня 5 10:01 myscript2
 11: 13: myscript2.log
 14: -rw-r - r-- 1 myusername mygroup 132 5 квітня 09:59 myscript2.log
 11: 13: other_file
 14: -rw-r - r-- 1 myusername mygroup   45 5 квітня 08:34 other_file
 17: 17: 19: i = 0
 19: ср, 05 квітня 2017 10:16:59
 17: 17: 19: i = 1
 19: ср, 05 квітня 2017 10:16:59
 17: 17: 19: i = 2
 19: ср, 05 квітня 2017 10:16:59
 17: 17: 22: 42
$

Примітки:

  • Як і відповідь l0b0 , це малоінвазивно - просто додайте рядок 2.
  • На відміну від відповіді l0b0 , тут не відображаються самі команди - але ви цього не вимагали.
  • Другий sleep, який охоплює рядки 6 та 7 сценарію, повідомляється як рядок 7.
  • Рядок 11 ( for f in *) повідомляється один раз перед кожною ітерацією цього forциклу.
  • echo "$f"і ls -ld "$f"правильно повідомляються у відповідних рядках (13 та 14).
  • Рядок 17 ( for ((i=0; i<3; i++))) повідомляється двічі перед кожною ітерацією цього forциклу та ще двічі після останньої ітерації.
  • В відміну set -x, LINENOі PS4 (які вказані в стандарті POSIX), то DEBUG trapє розширення баш і не буде працювати у всіх оболонках.
  • DEBUG trapможе виконувати будь-які команди (и), і не обмежується записом до стандартного виводу або стандартної помилки сценарію.

Питання говорить: «перевірте, який номер рядка bash-сценарію виконується« прямо зараз »», не вказуючи користувальницький інтерфейс. Інший підхід полягає в тому, щоб постійно записувати поточний номер рядка в файл журналу:

$ diff myscript myscript2
2c2
<trap 'printf "% 3d:" "$ LINENO"' DEBUG
---
> exec 6> myscript2.log && trap 'printf "% 3d \ n" "$ LINENO"> & 6' DEBUG
$ ./myscript2
Ср, 05 квітня 2017 10:23:50
Ср, 05 квітня 2017 10:24:20
Ср, 05 квітня 2017 10:24:31
всього 4
-rwxr-xr-x 1 myusername mygroup 221 5 квітня 10:01 таємниця
-rwxr-xr-x 1 myusername mygroup 252 квітня 5 10:01 myscript2
-rw-r - r-- 1 myusername mygroup   24 квітня 5 10:23 myscript2.log
-rw-r - r-- 1 myusername mygroup   45 5 квітня 08:34 other_file
таємницю
-rwxr-xr-x 1 myusername mygroup 221 5 квітня 10:01 таємниця
таємниця2
-rwxr-xr-x 1 myusername mygroup 252 квітня 5 10:01 myscript2
myscript2.log
-rw-r - r-- 1 myusername mygroup   60 5 квітня 10:23 myscript2.log
other_file
-rw-r - r-- 1 myusername mygroup   45 5 квітня 08:34 other_file
i = 0
Ср, 05 квітня 2017 10:24:31
i = 1
Ср, 05 квітня 2017 10:24:31
i = 2
Ср, 05 квітня 2017 10:24:31
42
$

Ми можемо стежити за виконанням цього сценарію, відстежуючи вміст myscript2.logфайлу з іншого терміналу. Наприклад, у другому sleep,

$ tail myscript2.log
  3
  4
  5
  7

6

Ви можете echo $LINENOв сценарії, і він повинен виводити будь-який рядок, в якому знаходиться ця команда.

#!/bin/bash
echo $LINENO

$ ./foo.sh
2

-1
#!/bin/bash -x

Додайте цей "-x" на початку вашого сценарію. Тоді кожен раз, коли ви виконуватимете скрипт, він буде відповідати лінії, яку виконує ваш сценарій. як дерево виконання вашого сценарію.


4
ОП вже відхилило цю пропозицію як незадовільну.
G-Man каже: "Відновіть Моніку"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.