bashスクリプトのどの行が実行されているかを確認する方法


15

そのラインをチェックする方法がある番号bash「今」が実行されているスクリプトは?

使用bash -x script.shは有望に見えます。ただし、現在の行番号を取得する必要があります。

回答:


20

スクリプト内で結合xtracePS4ます。

$ 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の答えが(より少ない程度に、そして、sorontarの)。それらの答えのように、私のもの$LINENOは行番号を発見するために使用します。それらとは異なりtrap、レポートをトリガーするために使用します。bashのtrapコマンドについては、bash(1)で説明しています。

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

    コマンドargは、シェルがシグナルsigspecを受信したときに読み取られて実行されます。…⁠︙
    sigspecDEBUGの場合、コマンド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"スクリプト内のすべてのコマンドの前にコマンドを、この出力を生成します。

$ ./myscript
  3:2017年4月5日水曜日10:16:17 AM
  4:5:2017年4月5日水曜日10:16:47 AM
  7:8:2017年4月5日水曜日10:16:58 AM
 10:合計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 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:2017年4月5日水曜日10:16:59 AM
 17:17:19:i = 1
 19:2017年4月5日水曜日10:16:59 AM
 17:17:19:i = 2
 19:2017年4月5日水曜日10:16:59 AM
 17:17:22:42
$

ノート:

  • 同様l0b0の答えは、これは、低侵襲性である-ちょうど2行を追加します。
  • l0b0の答えとは異なり、これはコマンド自体を表示しませんが、それを要求しませんでした。
  • 2 sleep行目は、スクリプトの行6と7にまたがっており、行7として報告されます。
  • 行11(for f in *)は、そのforループの各反復の前に1回報告されます。
  • echo "$f"そしてls -ld "$f"、それぞれの行(13および14)で正しく報告されます。
  • 17行目は、( for ((i=0; i<3; i++)))が報告されて二倍 というの各反復の前にforループ、そして二回以上、最後の反復後。
  • および (POSIX標準で指定されている)とは異なりset -x、DEBUG はbash拡張機能であり、すべてのシェルで機能するわけではありません。LINENOPS4trap
  • DEBUG trapは任意のコマンドを実行でき、スクリプトの標準出力または標準エラーへの書き込みに制限されません。

質問では、ユーザーインターフェイスを指定せずに、「今すぐ」bashスクリプトのどの行番号が実行されているかを確認します。別のアプローチは、現在の行番号をログファイルに継続的に書き込むことです。

$ diff myscript myscript2
2c2
<trap 'printf "%3d:" "$ LINENO"' DEBUG
---
> exec 6> myscript2.log && trap 'printf "%3d \ n" "$ LINENO">&6' DEBUG
$ ./myscript2
2017年4月5日水曜日10:23:50 AM
2017年4月5日水曜日午前10時24分20秒
2017年4月5日水曜日10:24:31 AM
合計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
マイスクリプト
-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
2017年4月5日水曜日10:24:31 AM
i = 1
2017年4月5日水曜日10:24:31 AM
i = 2
2017年4月5日水曜日10:24:31 AM
42
$

myscript2.log別の端末からファイルの内容を監視することにより、このスクリプトの実行を監視できます。たとえば、2番目の間にsleep

$ tail myscript2.log
  3
  4
  5
  7

6

次のことが可能echo $LINENOスクリプトで、それは、コマンドが上であることを起こることを何行出力する必要があります。

#!/bin/bash
echo $LINENO

$ ./foo.sh
2

-1
#!/bin/bash -x

スクリプトの先頭に「-x」を追加します。その後、スクリプトを実行するたびに、スクリプトが実行している行がエコーされます。スクリプトの実行ツリーのように。


4
OPは、この提案を不十分であるとして既に却下しています。
G-マンは「元に戻すモニカ言う
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.