シェルスクリプトを書くとき覚えておくこと一選
元ネタ: シェルスクリプトを書く時覚えておくこと一選! - rrreeeyyy.com
内容
set -euo pipefail
解説
Man ページから抜粋します。
$ man set : set [--abefhkmnptuvxBCEHPT] [-o option] [arg ...] set [+abefhkmnptuvxBCEHPT] [+o option] [arg ...] : -e Exit immediately if a pipeline (which may consist of a single simple command), a subshell command enclosed in parenthe- ses, or one of the commands executed as part of a command list enclosed by braces (see SHELL GRAMMAR above) exits with a non-zero status. The shell does not exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test following the if or elif reserved words, part of any command executed in a && or || list except the command following the final && or ||, any command in a pipeline but the last, or if the command's return value is being inverted with !. A trap on ERR, if set, is executed before the shell exits. This option applies to the shell environment and each subshell environment separately (see COMMAND EXECUTION ENVIRONMENT above), and may cause subshells to exit before executing all the commands in the subshell. : -o option-name The option-name can be one of the following: : pipefail If set, the return value of a pipeline is the value of the last (rightmost) command to exit with a non-zero sta- tus, or zero if all commands in the pipeline exit successfully. This option is disabled by default. : -u Treat unset variables and parameters other than the special parameters "@" and "*" as an error when performing parameter expansion. If expansion is attempted on an unset variable or parameter, the shell prints an error message, and, if not interactive, exits with a non-zero status. :
この内、私が元々知っていたのは "-e" だけでした。
かいつまんで解説すると以下の通り。
- "-e" ... エラー時に実行終了する。これをつけないと、途中でエラーが起きてもスクリプトは最後まで実行されてしまいますので、そうしたくないときによく使われます。
- "-o" ... オプションを指定します。ここでは "pipefail" を指定しています。
- "pipefail" ... その名の通りで、pipe で実行された途中のコマンドが異常終了したときは、コマンド全体の返り値をそれとするものです。詳しくは後述します。
- "-u" ... 特殊変数以外で未定義値を使用した場合にエラーとするものです。
pipefail オプションについて
下のようなスクリプトでテストしてみました。
#!/bin/sh set -o pipefail true | echo "pipe success" echo "return value=$?" false | echo "pipe failure" echo "return value=$?"
実行結果は以下のようになります。
pipe success return value=0 pipe failure return value=1
ここで、pipefail を無効にすると、後者の返り値も 0 になります。
また、set に -e オプションを付けると出力が以下のようになります。
pipe success return value=0 pipe failure
最後の echo コマンドは実行されずに終了します。 このとき、スクリプトの終了ステータス($?)は 1 です。