1. 概要

このチュートリアルでは、Bashスクリプトを実行せずに構文を検証する方法を学習します。 この目的で使用できるBashおよびサードパーティのユーティリティのいくつかを詳しく見ていきます。

2. 設定

まず、ほとんどのチュートリアルで使用するヘルパースクリプトを作成しましょう。

$ cat unity_check.sh
#! /bin/bash
read -p "Enter the input: " num1
if [ -z "$num1" ]
then
    echo "The number is empty"
    exit 0
fi
if [ "${num1}" -eq 1 ]
then
   echo "Number entered is 1"
else
   echo "Not equal to One !!"
fi

このスクリプトは、ユーザーが入力した数が1に等しいかどうかをテストします。

それでは、議論に飛び込み、構文的にそれを検証する方法を学びましょう。

3. noexecモードを使用した構文チェック

スクリプトを実行する前に構文的に検証したい場合があります。 so の場合、-nオプションを使用してnoexecモードを呼び出すことができます。 その結果、 Bashはコマンドを読み取りますが、実行しません

unity_check.shスクリプトをnoexecモードで実行してみましょう。

$ bash -n ./unity_check.sh
$

構文エラーがないため、これは空白の出力を生成します。 次に、スクリプトを少し変更して、2番目のif条件からthenステートメントを削除します。

$ cat unity_check_error.sh
#! /bin/bash
read -p "Enter the input: " num1
if [ -z "$num1" ]
then
    echo "The number is empty"
    exit 0
fi
if [ "${num1}" -eq 1 ]
   echo "Number entered is 1"
else
   echo "Not equal to One !!"
fi

スクリプトを実行してみましょう。

$ ./unity_check_error.sh
Enter the input: 2
./unity_check_error.sh: line 10: syntax error near unexpected token `else'
./unity_check_error.sh: line 10: `else'

特に、「予期しないトークンの近くの構文エラー」を理由として、スクリプトが失敗します。 さらに、空白の入力でもう一度実行してみましょう。

$ ./unity_check_error.sh
Enter the input:
The number is empty

興味深いことに、2番目の if ステートメントは評価されないため、ここではスクリプトが正常に実行されます。 さて、 スクリプトはいくつかのテストケースに合格し、いくつかのテストケースで失敗しました。 したがって、実行前に常に構文的にスクリプトを検証することは理にかなっています 。

スクリプトを検証しましょう:

$ bash -n ./unity_check_error.sh
./unity_check_error.sh: line 10: syntax error near unexpected token `else'
./unity_check_error.sh: line 10: `else'

予想どおり、構文の問題について通知されます。 また、スクリプトが実行されなかったため、ユーザー入力が要求されなかったことにも注意する必要があります。

4. noexecモードの使用に関する警告

スクリプトをもう一度変更してみましょう。今回は、最初のif条件から角かっこを削除します。

$ cat unity_check.sh
#! /bin/bash
read -p "Enter the input: " num1
if  -z "$num1" ]
then
    echo "The number is empty"
    exit 0
fi
if [ "${num1}" -eq 1 ]
then
   echo "Number entered is 1"
else
   echo "Not equal to One !!"
fi

それでは、 bash-nオプションを使用してスクリプトを検証しましょう。

$ bash -n ./unity_check.sh
$ 

興味深いことに、スクリプトはチェックに合格し、エラーは報告されません。 スクリプトを実行してみましょう:

$ ./unity_check.sh
Enter the input:
./unity_check.sh: line 3: -z: command not found
./unity_check.sh: line 8: [: : integer expression expected
Not equal to One !!

そして今、それはエラーを示しています!

[」は構文の一部ではないため、bash -n mode を使用してスクリプトを構文的に検証しているときに、このエラーをキャッチできませんでした「[」はテストコマンドの代替であり、bash-nは不足しているコマンドやコマンドのタイプミスをチェックしません。

5. シェルチェックツールの使用

前のセクションで見たように、 bash-nオプションを使用しているときにいくつかのエラーを見逃す可能性があります。 でも、 シェルスクリプトの静的分析には、いくつかのサードパーティツールを使用できます。 ShellCheckツールを分析してみましょう。

まず、Debian /UbuntuLinuxディストリビューションにShellCheckユーティリティをインストールするコマンドを確認しましょう。

$ apt install shellcheck

そして、RHEL / Fedora / CentOSディストリビューションの代替コマンド:

$ yum install ShellCheck

それでは、このツールを使用してセクション3のスクリプトを検証しましょう。

$ shellcheck unity_check_error.sh

In unity_check_error.sh line 8:
if [ "${num1}" -eq 1 ]
^-- SC1049: Did you forget the 'then' for this 'if'?
^-- SC1073: Couldn't parse this if expression. Fix to allow more checks.


In unity_check_error.sh line 10:
else
^-- SC1050: Expected 'then'.
    ^-- SC1072: Unexpected keyword/token. Fix any mentioned problems and try again.

For more information:
  https://www.shellcheck.net/wiki/SC1049 -- Did you forget the 'then' for thi...
  https://www.shellcheck.net/wiki/SC1050 -- Expected 'then'.
  https://www.shellcheck.net/wiki/SC1072 -- Unexpected keyword/token. Fix any...

予想どおり、thenステートメントが欠落していることを通知します。 それでは、ShellCheckユーティリティを使用してセクション4のスクリプトを検証しましょう。

$ shellcheck unity_check.sh

In unity_check.sh line 2:
read -p "Enter the input: " num1
^--^ SC2162: read without -r will mangle backslashes.


In unity_check.sh line 3:
if  -z "$num1" ]
    ^-- SC2215: This flag is used as a command name. Bad line break or missing [ .. ]?
               ^-- SC2171: Found trailing ] outside test. Add missing [ or quote if intentional.

For more information:
  https://www.shellcheck.net/wiki/SC2171 -- Found trailing ] outside test. Ad...
  https://www.shellcheck.net/wiki/SC2215 -- This flag is used as a command na...
  https://www.shellcheck.net/wiki/SC2162 -- read without -r will mangle backs...

すごい! bash -n コマンドでは識別できなかった、欠落している角かっこも識別できました。

6. 結論

このチュートリアルでは、Bashスクリプトを実行せずに構文を検証する方法を確認しました。

まず、bashnoexecモードについて学びました。 次に、このモードの警告を確認しました。 最後に、シェルスクリプトを実行せずに静的分析に使用できるサードパーティツールShellCheckを分析しました。