bashスクリプトを実行するときに行番号を表示する方法


89

私は、コマンドをたくさん持っているし、出力の多くを生成しますテストスクリプトを持っている私が使用しset -xたりset -vset -e、そのエラーが発生したときにスクリプトが停止します。ただし、問題を特定するために実行が停止した行を特定することは、依然としてかなり困難です。各行が実行される前にスクリプトの行番号を出力できる方法はありますか?または、set -x?によって生成されたコマンド展示の前に行番号を出力します。または、スクリプト行の場所の問題に対処できる方法があれば、非常に役立ちます。ありがとう。

回答:


161

すでに使用しているとのことですが-x。変数PS4は、値が、-xオプションが設定されたときにコマンドラインがエコーされる前に出力されるプロンプトであり、デフォルトで:スペースが続くことを示します。

(現在実行中のスクリプトまたはシェル関数の行番号)PS4を発行するように変更できますLINENO

たとえば、スクリプトが次のようになっている場合:

$ cat script
foo=10
echo ${foo}
echo $((2 + 2))

したがって、これを実行すると、行番号が出力されます。

$ PS4='Line ${LINENO}: ' bash -x script
Line 1: foo=10
Line 2: echo 10
10
Line 3: echo 4
4

http://wiki.bash-hackers.org/scripting/debuggingtipsは、PS4トレースに必要となる可能性のあるすべてのものを出力する究極のものを提供します。

export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'

4
「シェルスクリプトをデバッグする方法」でこれについて誰も言及していないのはなぜだろうか。。これは単なるよりもはるかに優れていますecho
Suvarna Pattayil 2014年

@VusP同意しましたが、不要なechoステートメントは避けるのが最善です。
devnull 2014年

2
行番号-x 印刷する必要があると思わずにはいられません。または、多分-行番号nx 含める必要があります。私にとって、それはそれらの「WTF」の瞬間の1つです...
jww 2016

1
男、PS4の調合についてもっと早く知っていたらよかったのに...それは私に多くの頭痛の種を救ったでしょう
niken 2017

2
\033[0;33m+(${BASH_SOURCE}:${LINENO}):\033[0m ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'一部の色の場合
Ulysse BN

35

Bashでは$LINENO、スクリプトが現在実行されている行番号が含まれます。

関数が呼び出された行番号を知る必要がある場合は、を試してください$BASH_LINENO。この変数は配列であることに注意してください。

例えば:

#!/bin/bash       

function log() {
    echo "LINENO: ${LINENO}"
    echo "BASH_LINENO: ${BASH_LINENO[*]}"
}

function foo() {
    log "$@"
}

foo "$@"

Bash変数の詳細については、ここを参照てください。


0

単純な(しかし強力な)解決策:echo問題の原因と思われるコードの周りに配置し、echoメッセージが画面に表示されなくなるまで1行ずつ移動します-以前のエラーのためにスクリプトが停止したためです。

さらに強力なソリューション:bashdbbashデバッガーをインストールし、スクリプトを1行ずつデバッグします


2
echo多くの場合、何かを処理することは役に立ちますが、意味のある、解析可能な出力を持つ関数に適用しようとすると不十分です。
エリランマルカ2017

1
@EliranMalkaフェアポイント。あなたはそのような場合には標準エラー出力にエコーがありますecho "foo" >&2
hek2mgl

1
...目的が本質的に診断的なメッセージである場合は、すべての場合にstderrにエコーする必要があります。
チャールズ・ダフィー

0

LINENOのないシェルの回避策

かなり洗練されたスクリプトでは、すべての行番号を表示したくありません。むしろ私は出力を制御したいと思います。

関数を定義する

echo_line_no () {
    grep -n "$1" $0 |  sed "s/echo_line_no//" 
    # grep the line(s) containing input $1 with line numbers
    # replace the function name with nothing 
} # echo_line_no

次のような引用符で使用します

echo_line_no "this is a simple comment with a line number"

出力は

16   "this is a simple comment with a line number"

ソースファイルのこの行の数が16の場合。

これは基本的に、ashまたは他のシェルのユーザーに対して。なしでbashスクリプト実行するときに行番号を表示する方法の質問に答えますLINENO

追加するものはありますか?

承知しました。なぜこれが必要なのですか?これをどのように処理しますか?これで何ができますか?この単純なアプローチは本当に十分または有用ですか?なぜこれをいじくり回したいのですか?

もっと知りたい?デバッグに関する考察を読む

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.