読者です 読者をやめる 読者になる 読者になる

weblog of key_amb

主にIT関連の技術メモ

シェルスクリプトを書くとき覚えておくこと一選

シェル

元ネタ: シェルスクリプトを書く時覚えておくこと一選! - 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 です。