シェルスクリプトは構文エラーにもかかわらず0exit_statusを返します。

シェルスクリプトは構文エラーにもかかわらず0exit_statusを返します。

次のスクリプトを考えてみましょう。

#!/bin/sh

foo=1
if [[ ! -z $foo ]]; then
    echo abc
fi

Bash構文[[...]]を使用し、Ubuntuでデフォルトのシェル(ダッシュ)を使用して実行すると、期待どおりに機能しません。しかし、戻りコードはまだゼロです。

$ ./tmp.sh
./tmp.sh: 4: ./tmp.sh: [[: not found
$ echo $?
0

終了コードが利用できない場合、スクリプトはこれらのエラーをどのように検出できますか?

ベストアンサー1

まず、なぜこれが起こるのかを説明します。POSIX シェルコマンド言語仕様 説明する:

ifコマンドの終了状態は、実行されたthenまたはelse複合リストの終了状態でなければならず、実行されていない場合は0でなければなりません。

あなたの場合、その部分は実行されず、終了ステータス0がthenないためです。elseBashを使用してこのスクリプトを実行すると、次のようにゼロになりますman bash

   if list; then list; [ elif list; then list; ] ... [ else list; ] fi

          The if list is executed.  If its exit status is zero,
          the then list is executed.  Otherwise, each elif list is
          executed in turn, and if its exit status is zero, the
          corresponding then list is executed and the command
          completes.  Otherwise, the else list is executed, if
          present.  The exit status is the exit sta‐ tus of the
          last command executed, or zero if no condition tested
          true.

終了コードが利用できない場合、スクリプトはこれらのエラーをどのように検出できますか?

私が考えることができる2つの方法があります。

  • スクリプトを変更できる場合は、elseif構文にいくつか追加してください。

      #!/bin/sh
    
      foo=1
      if [[ ! -z $foo ]]; then
          echo abc
      else
          echo not true
          exit 1
      fi
    
  • 誰かからifを受け取ったが修正したくない場合は、shパターンでshellcheck静的アナライザを使用してコードで可能なバグを見つけて、作成者に報告してください。

      $ shellcheck -s sh dash-exit-status.sh
    
      In dash-exit-status.sh line 4:
      if [[ ! -z $foo ]]; then
         ^-------------^ SC2039: In POSIX sh, [[ ]] is undefined.
            ^-- SC2236: Use -n instead of ! -z.
    
      For more information:
        https://www.shellcheck.net/wiki/SC2039 -- In POSIX sh, [[ ]] is undefined.
        https://www.shellcheck.net/wiki/SC2236 -- Use -n instead of ! -z.
    

基本的にこれ抜け穴私にとっては、実行しなければならないスクリプトでPOSIX以外の関数を使用してはいけません/bin/sh

おすすめ記事