Bashスクリプトを実行せずに構文チェックするにはどうすればよいですか?


回答:


380
bash -n scriptname

おそらく明らかな警告です:これは構文を検証しますが、bashスクリプトがパスではech helloなく、などのコマンドを実行しようとしているかどうかはチェックしませんecho hello


9
bashのマンページの「SHELL BUILTIN COMMANDS / set」の下に-nが記載されており、マンページの冒頭にあるように、bashはすべての単一文字オプションを解釈setします。
2008年

24
(私にとって)明白でない警告に追加するために、if ["$var" == "string" ]代わりに、欠落しているスペースによって引き起こされるエラーをキャッチしませんif [ "$var" == "string" ]
Brynjar

11
@Brynjarそれは単なる構文チェックだからです。左角かっこは構文ではなく、実行する関数の名前です。type [「[はシェル組み込みです」と言います。最終的にはtestプログラムに委任されますが、終了括弧も必要です。したがってif test"$var"、これは作成者が意図したものではありませんが、構文的には有効です($ varの値が "a"であるとすると、 "bash:testa:command not found"と表示されます)。ポイントは、構文的には、欠けているスペースがないということです。
Joshua Cheek

2
@JoshuaCheek:[この場合、$varたまたま空の文字列に展開された場合にのみ、組み込みが呼び出されます。場合$varに膨張し、空でない文字列が、[された連結その文字列とし、として解釈され、コマンド名(ない関数バッシュで名)、および、はい、それは構文的に有効な、しかし、明らかにあなたの状態、意図するところではないとして。の[[代わりにを使用すると[、(組み込みではなく)[[シェルキーワードであっても、意図しない文字列の連結によってキーワードの認識が上書きされるため、同じ結果が得られます。
mklement0

2
@JoshuaCheek:bashはまだ構文ここ-checking:それはチェックしています単純コマンド呼び出し構文を:["$var"ある 構文的に有効なコマンド名の発現; 同様に、トークン==とは、"$string"有効なコマンドです引数。(一般的には、組み込みが[で解析されたコマンドに対し、構文[[-シェルとしてキーワード -異なった解析されます。)シェル組み込みが[ないではない 委任「にtestプログラム」(外部ユーティリティ): 、bash、、dash すべて持っている組み込みの両方のバージョンとkshzsh[test、そして彼らは外部ユーティリティの対応物を呼び出しませ
mklement0 2015年

127

時間はすべてを変える。これは、シェルスクリプトのオンライン構文チェックを提供するWebサイトです。

一般的なエラーの検出は非常に強力であることがわかりました。

ここに画像の説明を入力してください

ShellCheckについて

ShellCheckは、sh / bashスクリプト用の静的分析およびリンティングツールです。これは主に、典型的な初級および中級レベルの構文エラーと、シェルが不可解なエラーメッセージまたは奇妙な動作を提供する落とし穴を処理することに焦点を当てていますが、コーナーケースが遅延障害を引き起こす可能性があるいくつかのより高度な問題についても報告します。

HaskellのソースコードはGitHubで入手できます!


5
素晴らしいヒント。OSX上であなたは今も、shellcheck.net CLIをインストールすることができますshellcheckを通じて、自作brew install shellcheck
mklement0

3
またdebian&friendsで:apt-get install shellcheck
その他の男

Ubuntu trustyの場合、このパッケージはからインストールする必要がありますtrusty-backports
Peterino、2015

上記のように、信頼できる依存関係が必要であり、ubuntu 14.04で以下のようにインストールできます:sudo apt-get -f install次に、sudo sudo apt-get install shellcheck
zhihong

これは本当に便利ですが、Bashのパーサーではなく独自のパーサーを使用しています。ほとんどの場合これで十分であり、解析と他の問題の両方を識別できますが、まったく同じ方法で解析されないエッジケースが少なくとも1つ(おそらく私が見たことのない他のケース)があります。
Daniel H

38

また、追加のチェックを行うために、作成するすべてのbashスクリプトで 'u'オプションを有効にします。

set -u 

これは、次のスクリプト「check_init.sh」のように、初期化されていない変数の使用を報告します

#!/bin/sh
set -u
message=hello
echo $mesage

スクリプトを実行する:

$ check_init.sh

以下を報告します:

./check_init.sh[4]:mesage:パラメータが設定されていません。

タイプミスを見つけるのに非常に役立ちます


4
それは「-o ERREXITセット」を行くためにこれらの、それの良い「セット-o nounset」「pipefail -oセット」を通過すれば、私は、私のbashスクリプトで常にこれらのフラグを設定する
μολὼν.λαβέ

set -uエラーメッセージを取得するにはスクリプトを実行する必要があるため、+ 1 は実際には質問の答えにはなりません。bash -n check_init.shその警告さえ示していません
rubo77

23
sh  -n   script-name 

これを実行します。スクリプトに構文エラーがある場合は、同じエラーメッセージが返されます。エラーがなければ、メッセージを出さずに出てきます。を使用するとecho $?、すぐに0確認でき、間違いなく成功したことを確認できます。

うまくいきました。Linux OS、Bash Shellで実行しました。


1
bash構文チェックに正確に関連しているわけではありませんが、スクリプト全体またはスクリプトのセクションをデバッグするためにset -xおよびset + xを使用することは非常に便利です
GuruM

これのおかげで-nについて知らなかった知らなかったが、私が欲しかったのは@GuruM> sh -x test.shで、スクリプトの生成された出力が表示されるためです
zzapper

1
はい。コマンドラインで次の操作を実行できることを忘れていました。1)bash -x test.sh#これにより、スクリプト全体が「デバッグモード」で実行されます。2)+ xを設定します。bash test.sh; set -x #set debug mode on / off before / after script runスクリプト内:a)#!/ bin / bash -x #add 'debug mode' at top of script b)set + x; コード; スクリプトの任意のセクションにset -x #add 'debug mode'
GuruM

sh -nおそらく、スクリプトが有効なBashスクリプトであることを確認しません。それは偽陰性を与えるかもしれません。sh通常はBashではないBourneシェルの変種です。たとえば、Ubuntu Linuxではrealpath -e $(command -v sh)/ bin / dash
jarno

4

私は実際に、findツールを使用して実行せずに、現在のディレクトリ内のすべてのbashスクリプトに構文エラーがないかチェックします。

例:

find . -name '*.sh' -exec bash -n {} \;

単一のファイルに使用する場合は、ファイルの名前でワイルドカードを編集します。


3

nullコマンド[コロン]は、変数の値を確認するためのデバッグにも役立ちます。

set -x
for i in {1..10}; do
    let i=i+1
    : i=$i
done
set - 

パラメータ拡張を使用している
mug896

これは機能しset -xます。実行される前にすべての行を表示するからです
rubo77

1

構文をチェックするIntelliJ IDEA用のBashSupportプラグインがあります。


しかし、ファイルが.shBashスクリプトに関連付けられている拡張子やその他の拡張子がない場合は機能しません。これは、ERBなどのテンプレートツールを使用してスクリプトを生成する場合に該当します(その後、で終了します.erb)。修正したい場合は、youtrack.jetbrains.com / issue / IDEA-79574に投票してください!
Greg Dubicki 2016

1

変数にディレクトリ内のすべてのファイルの有効性が必要な場合(git pre-commitフック、ビルドlintスクリプト)、「sh -n」または「bash -n」コマンドのstderr出力をキャッチできます(他を参照)回答)変数内にあり、それに基づく「if / else」を持っている

bashErrLines=$(find bin/ -type f -name '*.sh' -exec sh -n {} \;  2>&1 > /dev/null)
  if [ "$bashErrLines" != "" ]; then 
   # at least one sh file in the bin dir has a syntax error
   echo $bashErrLines; 
   exit; 
  fi

必要に応じて、「sh」を「bash」に変更します

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.