- 1 はじめに
- 2 検証環境
- 3 スクリプトにデバッグオプションを設定する方法
- 4 bashコマンドの引数にデバッグオプションを指定する方法
- 5 デバッガを使う方法(bashdb)
- 6 スクリプトの構文をチェックする方法(ShellCheck)
- Z 参考情報
1 はじめに
2 検証環境
AlmaLinux版数は以下のとおりです。
[root@server ~]# cat /etc/redhat-release AlmaLinux release 8.6 (Sky Tiger)
カーネル版数は以下のとおりです。
[root@server ~]# uname -r 4.18.0-372.9.1.el8.x86_64
bashの版数は以下のとおりです。
[root@server ~]# bash --version bash --version GNU bash, バージョン 4.4.20(1)-release (x86_64-redhat-linux-gnu) -snip-
3 スクリプトにデバッグオプションを設定する方法
3.1 スクリプトが実行する処理を表示する方法(-x)
"-x"は、スクリプトが実行する処理を表示するオプションです。このオプションは、スクリプトの1行目のシバンに設定します。
[root@server ~]# cat tp.sh #!/usr/bin/bash -x if [ "$1" -eq 1 ]; then echo 'one' elif [ "$1" -eq 2 ]; then echo 'two' else echo 'other' fi
スクリプトを実行します。スクリプトが実行した処理が表示されます。
[root@server ~]# ./tp.sh 3 + '[' 3 -eq 1 ']' + '[' 3 -eq 2 ']' + echo other other
3.2 エラーが発生したらスクリプトを終了する方法(set -e/set +e)
"-e"は、スクリプト実行中にエラーが発生した場合、実行を終了するオプションです。これにより、エラーが発生した場所を迅速に特定することができます。一方で、"+e"は停止する動作を無効にするオプションです。
3.2.1 スクリプト全体に適用する方法(set -e)
2番目のlsコマンドが存在しないコマンドパスに対して実行するスクリプトを作成します。
[root@server ~]# cat tp.sh #!/usr/bin/bash ls /usr/bin/bash ls /usr/bin/1111 ls /usr/bin/date
スクリプトを実行します。2つ目のlsコマンド実行時にエラーが発生しましたが、スクリプトは最後まで実行されました。
[root@server ~]# ./tp.sh /usr/bin/bash ls: '/usr/bin/1111' にアクセスできません: そのようなファイルやディレクトリはありません /usr/bin/date
スクリプト先頭にset -eを追加します。
[root@server ~]# cat tp.sh #!/usr/bin/bash set -e ls /usr/bin/bash ls /usr/bin/1111 ls /usr/bin/date
スクリプトを実行します。2つ目のlsコマンドの実行時にエラーが発生し、そのためスクリプトが終了したことがわかります。
[root@server ~]# ./tp.sh /usr/bin/bash ls: '/usr/bin/1111' にアクセスできません: そのようなファイルやディレクトリはありません
3.2.2 スクリプトの一部分に適用する方法(set -e/set +e)
lsコマンドの前後に"-e"オプションと"+e"オプションを指定したスクリプトを作成します。
[root@server ~]# cat tp.sh #!/usr/bin/bash set -e ls /usr/bin/bash set +e ls /usr/bin/1111 ls /usr/bin/date
スクリプトを実行します。-e/+eオプションは、1つ目のlsコマンドまでの有効範囲に限られるため、2つ目のlsコマンドでエラーが発生しても、スクリプトは停止しません。
[root@server ~]# ./tp.sh /usr/bin/bash ls: '/usr/bin/1111' にアクセスできません: そのようなファイルやディレクトリはありません /usr/bin/date
3.3 変数未設定を検出する方法(-u)
"-u"オプションを指定したスクリプトを作成します。このスクリプトは、変数に値が設定されていない場合に警告を表示します。例として、変数var1に値を設定し、一方で変数var2には値を設定しません。
[root@server ~]# cat tp.sh #!/usr/bin/bash var1="xxx" echo ${var1} echo ${var2}
スクリプトを実行します。変数var1に設定した値のみが表示されていることがわかります。
[root@server ~]# ./tp.sh xxx [root@server ~]#
スクリプトの終了ステータスを確認すると、正常終了(ステータスコード: 0)であることがわかります。
[root@server ~]# echo $? 0
次に、"-u"オプションを設定したスクリプトを作成します。
[root@server ~]# cat tp.sh #!/usr/bin/bash set -u var1="xxx" echo ${var1} echo ${var2}
スクリプトを実行します。
[root@server ~]# ./tp.sh xxx ./tp.sh: 行 7: var2: 未割り当ての変数です
スクリプトの終了ステータスを確認すると、異常終了(ステータスコード: 0以外)であることが確認できます。
[root@server ~]# echo $? 1
3.4 パイプ処理でエラーが発生したらパイプ処理全体でエラーにする方法(-u)
スクリプト内で参照するためのテスト用ファイルを作成します。
[root@server ~]# cat log.txt 111
パイプライン中のgrepコマンドは異常終了しますが、その後のsortコマンドが正常終了するテスト用のスクリプトを作成します。なお、なお、"-u"オプションは未設定とします。
[root@server ~]# cat tp.sh #!/usr/bin/bash cat log.txt | grep xxx | sort
スクリプトを実行します。
[root@server ~]# ./tp.sh
grepコマンドは異常終了しますが、sortコマンドが正常終了するため、パイプ全体の終了ステータスは正常終了(ステータスコード: 0)となります。そのため、スクリプトの終了ステータスを確認すると、0であることがわかります。
[root@server ~]# echo $? 0
次に、"-u"オプションを設定したスクリプトを作成します。
[root@server ~]# cat tp.sh #!/usr/bin/bash set -o pipefail cat log.txt | grep xxx | sort
スクリプトを実行します。
[root@server ~]# ./tp.sh
スクリプトの終了ステータスを確認すると、1であることがわかります。
[root@server ~]# echo $? 1
4 bashコマンドの引数にデバッグオプションを指定する方法
スクリプトに設定したオプションは、bashコマンドの引数として使用することができます。例えば、"-x"オプションを使用すると、以下のようになります
テスト用のスクリプトを作成します。
[root@server ~]# cat tp.sh #!/usr/bin/bash if [ "$1" -eq 1 ]; then echo 'one' elif [ "$1" -eq 2 ]; then echo 'two' else echo 'other' fi
bashコマンドの引数として"-x"を指定すると、スクリプトの実行過程で実行されたコマンドが表示されるため、スクリプトの実行内容を確認することができます。
[root@server ~]# bash -x tp.sh 3 + '[' 3 -eq 1 ']' + '[' 3 -eq 2 ']' + echo other other
5 デバッガを使う方法(bashdb)
詳細は以下を参照してください。
bashdbの使い方 - hana_shinのLinux技術ブログ
6 スクリプトの構文をチェックする方法(ShellCheck)
詳細は以下を参照してください。
ShellCheckコマンドの使い方 - hana_shinのLinux技術ブログ
Z 参考情報
私が業務や記事執筆で参考にした書籍を以下のページに記載します。
Linux技術のスキルアップをしよう! - hana_shinのLinux技術ブログ