LoginSignup
9
4

bash シェルのスクリプトで現在の実行行/呼び出し行の取得(行番号の取得)

Last updated at Posted at 2018-08-15

ファイル上の現在の行番号を Bash のスクリプト内で取得したい。

例えば Perl や PHP の「__LINE__」や Golang の _, _, line, _ := runtime.Caller(0) のように。

他の言語では実行行の取得は分かっていたのですが、「シェルの場合は何だっけ」と Qiita 記事に絞ってsite:qiita.com シェル 現在の実行行 行番号 取得」とググってもすぐに見つからなかったので、自分のググラビリティとして。

TL; DR (今北産業)

  1. シェル変数の「$LINENO」を使う。ラインナンバーの略。
  2. 関数の「呼び出し元の実行行」を取得したい場合は「$BASH_LINENO
  3. 動くサンプルをおくれ。
sample_lineno.sh
#!/bin/bash

echo $LINENO
echo $LINENO
実行結果
$ ./sample_lineno.sh
3
4
sample_bash_lineno.sh
#!/bin/bash

hoge () {
    echo "Called from line:${BASH_LINENO[0]}"
}

hoge
hoge
実行結果
$ ./sample_bash_lineno.sh
Called from line:7
Called from line:8

動作確認済み環境

  • macOS HighSierra(OSX 10.13.6)
  • bash --version: GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)

TS; DR (用途に関するコマケーこと)

実行行の取得は、一般的には LOG 出力に使うことが多いと思います。しかし、今回は終了ステータスのコードを実行行にしたかったのです。

つまり、スクリプトを exit する際の "0"(正常終了)以外の場合、通常はエラー番号(エラーコード)を "1" や独自のエラーコードにするところを、「exit した行」にしたかったのです。

sample.sh
#!/bin/bash

dir_curr=$(cd $(dirname $0); pwd)

# Make temp directory
# -------------------
echo -n 'Now creating temporary directory ... '
dir_temp=$(mktemp -d)
if [ $? -gt 0 ]; then
    echo ' NG'
    echo '* Error while creating temp directory.'; exit $LINENO
fi
echo 'OK'

# Moving to temp directory
# ------------------------
echo -n 'Now changing work directory to temporary ... '
cd $dir_temp
if [ $? -gt 0 ]; then
    echo ' NG'
    echo '* Error while changing work to temp directory.'; exit $LINENO
fi
echo 'OK'

exit 0

PHP や Golang などからシェル・スクリプトを外部コマンドとして実行した際、問題があった場合に標準エラー出力(STDERR)と共に、エラー番号に意味を持たせたかったのです。

しかし、横着なため管理しきれず、「どうせソースを見に行くんだから行番号の方が楽でいいや」と**「エラー番号 = エラーで抜けた行」に統一**することにしました。_(:⁍」 )_

注意点として、bash の終了ステータス番号は1バイト、つまり 0-255 の整数です。255 を越えると 0 から再度カウントされた値が出力されます。

つまり、$EXIT_NUM % 256 と 256 で mod(剰余) されて出力されるのです。

第1引数を終了ステータス番号として「exit」するだけのスクリプトでテスト
$ # テスト・スクリプト
$ cat sample.sh
#!/usr/bin/env bash
exit $1

$ # テスト
$ ./sample.sh 10 ; echo $?
10

$ ./sample.sh 255 ; echo $?
255

$ ./sample.sh 256 ; echo $?
0

$ ./sample.sh 257 ; echo $?
1

このように、「エラー番号=終了行」とする手法を使う場合、スクリプトは 255 行以内に抑える必要があります。偶然にも 256 行目でエラーが発生しても 0 となり正常終了扱いになったり、256 行目以降では追跡できなくなるからです。

そのため私の場合、スクリプトは 256 行以上になるならファイルをわけるという方針でカバーしています。

256 行以内に抑えることが難しい場合は、別のスクリプトにわけてメインのスクリプトから呼び出すことも可能です。

source でスクリプトを include しても動作する

別のスクリプト・ファイルにわける場合は、source <inclueするファイルのパス> で可能です。その際に、include する側は $BASH_LINENO で「呼び出し元の行番号」を取得できます。

sample1.sh
function function1(){
  echo $BASH_LINENO
}
Main.sh
#!/bin/bash

source sample1.sh
function1
./Main.sh
4
9
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
4