ShellCheck は、bash/sh シェル スクリプトに関する警告と提案を提供する GPLv3 ツールです。
ShellCheck の目標は次のとおりです。
シェルで不可解なエラー メッセージが表示される原因となる典型的な初心者向けの構文問題を指摘し、明確にします。
シェルが奇妙で直観に反する動作を引き起こす典型的な中間レベルのセマンティック問題を指摘し、明確にします。
上級ユーザーの本来動作しているスクリプトが将来の状況で失敗する可能性がある、微妙な注意点、特殊なケース、落とし穴を指摘します。
ShellCheck が識別に役立つ例については、不良コードのギャラリーを参照してください。
ShellCheck を使用するにはさまざまな方法があります。
https://www.shellcheck.net にシェル スクリプトを貼り付けて、すぐにフィードバックを取得します。
ShellCheck.net は常に最新の git commit と同期されており、ShellCheck を試す最も簡単な方法です。友達に教えてください!
上記のように、ターミナルでshellcheck yourscript
して実行すると、すぐに出力されます。
ShellCheck の提案は、さまざまなエディターで直接確認できます。
。
。
Sublime、SublimeLinter 経由。
Pulsar Edit (旧 Atom)、linter-shellcheck-pulsar 経由。
VSCode、vscode-shellcheck 経由。
他のほとんどのエディターは、GCC エラー互換性を介して使用されます。
ShellCheck は主に対話型の使用を目的としていますが、ビルドやテスト スイートに簡単に追加できます。終了コードを標準的に使用するため、プロセスの一部としてshellcheck
コマンドを追加するだけで済みます。
たとえば、Makefile では次のようになります。
check-scripts :
# Fail if any of these files have warnings
shellcheck myscripts/*.sh
または Travis CI .travis.yml
ファイル内:
script :
# Fail if any of these files have warnings
- shellcheck myscripts/*.sh
ShellCheck がプリインストールされており、すぐに使用できるサービスとプラットフォーム:
GitLab を含む他のほとんどのサービスでは、システムのパッケージ マネージャー (「インストール」を参照) を使用するか、バイナリ リリースをダウンロードして解凍することによって、ShellCheck を自分でインストールできます。
いずれにしても、特定の ShellCheck バージョンを手動でインストールすることをお勧めします。これにより、新しい警告が含まれる新しいバージョンが公開されたときに、予期せぬビルドの中断が回避されます。
カスタマイズされたフィルタリングまたはレポートの場合、ShellCheck は単純な JSON、CheckStyle 互換 XML、GCC 互換警告、および人間が判読できるテキスト (ANSI カラーの有無にかかわらず) を出力できます。詳細については、統合 wiki ページを参照してください。
ShellCheck をローカルにインストールする最も簡単な方法は、パッケージ マネージャーを使用することです。
Cabal を備えたシステムの場合 ( ~/.cabal/bin
にインストール):
cabal update
cabal install ShellCheck
スタックを備えたシステムの場合 ( ~/.local/bin
にインストール):
stack update
stack install ShellCheck
Debian ベースのディストリビューションの場合:
sudo apt install shellcheck
Arch Linux ベースのディストリビューションの場合:
pacman -S shellcheck
または、依存関係のないshellcheck-binをAURから取得します。
Gentoo ベースのディストリビューションの場合:
emerge --ask shellcheck
EPEL ベースのディストリビューションの場合:
sudo yum -y install epel-release
sudo yum install ShellCheck
Fedora ベースのディストリビューションの場合:
dnf install ShellCheck
FreeBSD の場合:
pkg install hs-ShellCheck
Homebrew を使用した macOS (OS X) の場合:
brew install shellcheck
または MacPorts を使用する場合:
sudo port install shellcheck
OpenBSD の場合:
pkg_add shellcheck
openSUSE の場合
zypper in ShellCheck
または、OneClickInstall を使用します - https://software.opensuse.org/package/ShellCheck
ソルスについて:
eopkg install shellcheck
Windows の場合 (chocolatey 経由):
C: > choco install shellcheck
または Windows (winget 経由):
C: > winget install --id koalaman.shellcheck
または Windows (スクープ経由):
C: > scoop install shellcheck
conda-forge から:
conda install -c conda-forge shellcheck
スナップストアより:
snap install --channel=edge shellcheck
Docker Hub から:
docker run --rm -v " $PWD :/mnt " koalaman/shellcheck:stable myscript
# Or :v0.4.7 for that version, or :latest for daily builds
または、より大きな Alpine Linux ベースのイメージを拡張する場合は、 koalaman/shellcheck-alpine
を使用します。通常の Alpine イメージとまったく同じように動作しますが、shellcheck がプリインストールされています。
nix パッケージマネージャーの使用:
nix-env -iA nixpkgs.shellcheck
Flox パッケージマネージャーの使用
flox install shellcheck
あるいは、最新リリースのコンパイル済みバイナリをここからダウンロードできます。
または、他のリリースについては GitHub リリース (毎日の Git ビルドの最新メタリリースを含む) を参照してください。
現在、Apple Silicon の公式バイナリはありませんが、Visual Studio Code 用の ShellCheck を介してサードパーティのビルドを入手できます。
ディストリビューション パッケージにはすでにman
ページが付属しています。ソースからビルドしている場合は、次のようにインストールできます。
pandoc -s -f markdown-smart -t man shellcheck.1.md -o shellcheck.1
sudo mv shellcheck.1 /usr/share/man/man1
プリコミット経由で ShellCheck を実行するには、フックを.pre-commit-config.yaml
に追加します。
repos:
- repo: https://github.com/koalaman/shellcheck-precommit
rev: v0.7.2
hooks:
- id: shellcheck
# args: ["--severity=warning"] # Optionally only show errors and warnings
Travis CI にはデフォルトで ShellCheck が統合されているため、手動でインストールする必要はありません。
いつでもアップグレードするため、または最新リリースを使用していることを確認するためにアップグレードしたい場合は、以下の手順に従ってバイナリ バージョンをインストールしてください。
プリコンパイルされたバイナリはtar.xz
ファイルで提供されます。これらを解凍するには、 xz
がインストールされていることを確認してください。 Debian/Ubuntu/Mint では、 apt install xz-utils
できます。 Redhat/Fedora/CentOS では、 yum -y install xz
。
単純なインストーラーは次のようなことを実行します。
scversion= " stable " # or "v0.4.7", or "latest"
wget -qO- " https://github.com/koalaman/shellcheck/releases/download/ ${scversion?} /shellcheck- ${scversion?} .linux.x86_64.tar.xz " | tar -xJv
cp " shellcheck- ${scversion} /shellcheck " /usr/bin/
shellcheck --version
このセクションでは、ソース ディレクトリから ShellCheck をビルドする方法について説明します。 ShellCheck は Haskell で書かれており、コンパイルには 2GB の RAM が必要です。
ShellCheck は、Cabal を使用して構築およびパッケージ化されています。システムのパッケージ マネージャーからcabal-install
パッケージをインストールします (例: apt-get
、 brew
、 emerge
、 yum
、またはzypper
を使用)。
macOS (OS X) では、brew を使用して Cabal を高速インストールできます。ソースからコンパイルしようとすると 30 分以上かかりますが、数分かかります。
$ brew install cabal-install
MacPorts では、パッケージはhs-cabal-install
と呼ばれますが、ネイティブ Windows ユーザーは https://www.haskell.org/platform/ から Haskell プラットフォームの最新バージョンをインストールする必要があります。
cabal
がインストールされていることを確認し、その依存関係リストを次のように更新します。
$ cabal update
このリポジトリをgit clone
、ShellCheck ソース ディレクトリにcd
てビルド/インストールします。
$ cabal install
これにより、ShellCheck がコンパイルされ、 ~/.cabal/bin
ディレクトリにインストールされます。
このディレクトリをPATH
に追加します (bash の場合、これを~/.bashrc
に追加します)。
export PATH= " $HOME /.cabal/bin: $PATH "
ログアウトして再度ログインし、PATH が正しく設定されていることを確認します。
$ which shellcheck
~ /.cabal/bin/shellcheck
ネイティブ Windows では、 PATH
すでに設定されているはずですが、システムはレガシー コードページを使用する可能性があります。 cmd.exe
、 powershell.exe
および Powershell ISE では、ラスター フォントではなく TrueType フォントを使用し、 chcp
でアクティブ コードページを UTF-8 (65001) に設定してください。
chcp 65001
Powershell ISE では、出力エンコーディングをさらに更新する必要がある場合があります。
[ Console ]::OutputEncoding = [ System.Text.Encoding ]::UTF8
単体テスト スイートを実行するには:
$ cabal test
では、ShellCheck はどのようなことを調べるのでしょうか?以下は、検出された問題の不完全なリストです。
ShellCheck は、いくつかのタイプの間違った引用を認識できます。
echo $1 # Unquoted variables
find . -name * .ogg # Unquoted find/grep patterns
rm " ~/my file.txt " # Quoted tilde expansion
v= ' --verbose="true" ' ; cmd $v # Literal quotes in variables
for f in " *.ogg " # Incorrectly quoted 'for' loops
touch $@ # Unquoted $@
echo ' Don ' t forget to restart ! ' # Singlequote closed by apostrophe
echo ' Don ' t try this at home ' # Attempting to escape ' in ' '
echo ' Path is $PATH ' # Variables in single quotes
trap " echo Took ${SECONDS} s " 0 # Prematurely expanded trap
unset var[i] # Array index treated as glob
ShellCheck は、さまざまな種類の間違ったテスト ステートメントを認識できます。
[[ n != 0 ]] # Constant test expressions
[[ -e * .mpg ]] # Existence checks of globs
[[ $foo == 0 ]] # Always true due to missing spaces
[[ -n " $foo " ]] # Always true due to literals
[[ $foo =~ " fo+ " ]] # Quoted regex in =~
[ foo =~ re ] # Unsupported [ ] operators
[ $1 -eq " shellcheck " ] # Numerical comparison of strings
[ $n && $m ] # && in [ .. ]
[ grep -q foo file ] # Command without $(..)
[[ " $$ file " == * .jpg ]] # Comparisons that can't succeed
(( 1 - lt 2 )) # Using test operators in ((..))
[ x ] & [ y ] | [ z ] # Accidental backgrounding and piping
ShellCheck は、コマンドが正しく使用されていないインスタンスを認識できます。
grep ' *foo* ' file # Globs in regex contexts
find . -exec foo {} && bar {} ; # Prematurely terminated find -exec
sudo echo ' Var=42 ' > /etc/profile # Redirecting sudo
time --format=%s sleep 10 # Passing time(1) flags to time builtin
while read h ; do ssh " $h " uptime # Commands eating while loop input
alias archive= ' mv $1 /backup ' # Defining aliases with arguments
tr -cd ' [a-zA-Z0-9] ' # [] around ranges in tr
exec foo ; echo " Done! " # Misused 'exec'
find -name * .bak -o -name * ~ -delete # Implicit precedence in find
# find . -exec foo > bar ; # Redirections in find
f () { whoami ; }; sudo f # External use of internal functions
ShellCheck は、初心者によくある多くの構文エラーを認識します。
var = 42 # Spaces around = in assignments
$foo =42 # $ in assignments
for $var in * ; do ... # $ in for loop variables
var $n = " Hello " # Wrong indirect assignment
echo ${var $n } # Wrong indirect reference
var=(1, 2, 3) # Comma separated arrays
array=( [index] = value ) # Incorrect index initialization
echo $var [14] # Missing {} in array references
echo " Argument 10 is $1 0 " # Positional parameter misreference
if $( myfunction ) ; then .. ; fi # Wrapping commands in $()
else if othercondition ; then .. # Using 'else if'
f ; f () { echo " hello world; } # Using function before definition
[ false ] # 'false' being true
if ( -f file ) # Using (..) instead of test
ShellCheck はスタイルを改善するための提案を行うことができます。
[[ -z $( find /tmp | grep mpg ) ]] # Use grep -q instead
a >> log ; b >> log ; c >> log # Use a redirection block instead
echo " The time is ` date ` " # Use $() instead
cd dir ; process * ; cd .. ; # Use subshells instead
echo $[1+2] # Use standard $((..)) instead of old $[]
echo $(( $RANDOM % 6 )) # Don't use $ on variables in $((..))
echo " $( date ) " # Useless use of echo
cat file | grep foo # Useless use of cat
ShellCheck は、データと入力に関する問題を認識できます。
args= " $@ " # Assigning arrays to strings
files=(foo bar) ; echo " $files " # Referencing arrays as strings
declare -A arr=(foo bar) # Associative arrays without index
printf " %sn " " Arguments: $@ . " # Concatenating strings and arrays
[[ $# > 2 ]] # Comparing numbers as strings
var=World ; echo " Hello " var # Unused lowercase variables
echo " Hello $name " # Unassigned lowercase variables
cmd | read bar ; echo $bar # Assignments in subshells
cat foo | cp bar # Piping to commands that don't read
printf ' %s: %sn ' foo # Mismatches in printf argument count
eval " ${array[@]} " # Lost word boundaries in array eval
for i in " ${x[@]} " ; do ${x[$i]} # Using array value as key
ShellCheck は、スクリプトの堅牢性を向上させるための提案を行うことができます。
rm -rf " $STEAMROOT / " * # Catastrophic rm
touch ./-l ; ls * # Globs that could become options
find . -exec sh -c ' a && b {} ' ; # Find -exec shell injection
printf " Hello $name " # Variables in printf format
for f in $( ls * .txt ) ; do # Iterating over ls output
export MYVAR= $( cmd ) # Masked exit codes
case $version in 2. * ) : ;; 2.6. * ) # Shadowed case branches
ShellCheck は、シバンでサポートされていない機能を使用すると警告を出します。たとえば、シバンを#!/bin/sh
に設定すると、ShellCheck はcheckbashisms
と同様の移植性の問題について警告します。
echo {1.. $n } # Works in ksh, but not bash/dash/sh
echo {1..10} # Works in ksh and bash, but not dash/sh
echo -n 42 # Works in ksh, bash and dash, undefined in sh
expr match str regex # Unportable alias for `expr str : regex`
trap ' exit 42 ' sigint # Unportable signal spec
cmd & > file # Unportable redirection operator
read foo < /dev/tcp/host/22 # Unportable intercepted files
foo-bar () { .. ; } # Undefined/unsupported function name
[ $UID = 0 ] # Variable undefined in dash/sh
local var=value # local is undefined in sh
time sleep 1 | sleep 5 # Undefined uses of 'time'
ShellCheck は、他にもさまざまな問題を認識します。
PS1= ' e[0;32m$e[0m ' # PS1 colors not in [..]
PATH= " $PATH :~/bin " # Literal tilde in $PATH
rm “file” # Unicode quotes
echo " Hello world " # Carriage return / DOS line endings
echo hello # Trailing spaces after
var=42 echo $var # Expansion of inlined environment
! # bin/bash -x -e # Common shebang errors
echo $(( n / 180 * 100 )) # Unnecessary loss of precision
ls * [:digit:].txt # Bad character class globs
sed ' s/foo/bar/ ' file > file # Redirecting to input
var2= $var2 # Variable assigned to itself
[ x $var = xval ] # Antiquated x-comparisons
ls () { ls -l " $@ " ; } # Infinitely recursive wrapper
alias ls= ' ls -l ' ; ls foo # Alias used before it takes effect
for x ; do for x ; do # Nested loop uses same variable
while getopts " a " f ; do case $f in " b " ) # Unhandled getopts flags
最初は「shellcheck は素晴らしい」と思うかもしれませんが、その後「なんてことだ、まだ bash を使っているのか」と思うでしょう。
アレクサンダー・タラシコフ、Twitter経由
問題は、環境変数、コマンドラインを使用して、ファイル内で個別にまたはグローバルに無視できます。
https://github.com/koalaman/shellcheck/wiki/Ignore
バグや機能の提案については、GitHub 問題トラッカーを使用してください。
https://github.com/koalaman/shellcheck/issues
コードまたはドキュメントへのパッチを GitHub プル リクエストとして送信してください。 ShellCheck Wiki の DevGuide を確認してください。
貢献物は GNU GPLv3 に基づいてライセンスを取得する必要があります。投稿者が著作権を保有します。
ShellCheck は、GNU General Public License v3 に基づいてライセンスされています。このライセンスのコピーは、LICENSE ファイルに含まれています。
著作権 2012 ~ 2019 年、Vidar 'koala_man' Holen および寄稿者。
シェルチェックを楽しんでください!