ShellCheck는 bash/sh 쉘 스크립트에 대한 경고 및 제안을 제공하는 GPLv3 도구입니다.
ShellCheck의 목표는 다음과 같습니다.
쉘이 알 수 없는 오류 메시지를 표시하게 만드는 일반적인 초보자의 구문 문제를 지적하고 명확히 합니다.
쉘이 이상하고 반직관적으로 동작하게 만드는 일반적인 중간 수준 의미론적 문제를 지적하고 명확히 합니다.
향후 상황에서 고급 사용자의 작업 스크립트가 실패할 수 있는 미묘한 경고, 특수 사례 및 함정을 지적합니다.
ShellCheck가 식별하는 데 도움이 되는 예를 보려면 잘못된 코드 갤러리를 참조하세요!
ShellCheck를 사용하는 방법에는 여러 가지가 있습니다!
즉각적인 피드백을 받으려면 https://www.shellcheck.net에 셸 스크립트를 붙여넣으세요.
ShellCheck.net은 항상 최신 git 커밋과 동기화되며 ShellCheck를 시도하는 가장 쉬운 방법입니다. 친구들에게 알려주세요!
위에 표시된 대로 즉시 출력하려면 터미널에서 shellcheck yourscript
실행하세요.
다양한 편집기에서 ShellCheck 제안을 직접 볼 수 있습니다.
.
.
SublimeLinter를 통한 Sublime.
linter-shellcheck-pulsar를 통한 Pulsar Edit(이전 Atom).
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 색상 포함 또는 제외)를 출력할 수 있습니다. 자세한 문서는 통합 위키 페이지를 참조하세요.
ShellCheck를 로컬로 설치하는 가장 쉬운 방법은 패키지 관리자를 이용하는 것입니다.
Cabal이 포함된 시스템( ~/.cabal/bin
에 설치):
cabal update
cabal install ShellCheck
Stack이 있는 시스템( ~/.local/bin
에 설치):
stack update
stack install ShellCheck
Debian 기반 배포판의 경우:
sudo apt install shellcheck
Arch Linux 기반 배포판의 경우:
pacman -S shellcheck
또는 AUR에서 종속성이 없는 shellcheck-bin을 얻으세요.
젠투 기반 배포판:
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
오픈수세에서
zypper in ShellCheck
또는 OneClickInstall - https://software.opensuse.org/package/ShellCheck를 사용하세요.
솔루스에서:
eopkg install shellcheck
Windows에서(초콜릿을 통해):
C: > choco install shellcheck
또는 Windows(winget을 통해):
C: > winget install --id koalaman.shellcheck
또는 Windows(특종을 통해):
C: > scoop install shellcheck
콘다 포지에서:
conda install -c conda-forge shellcheck
Snap 스토어에서:
snap install --channel=edge shellcheck
Docker 허브에서:
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
또는 여기에서 최신 릴리스용으로 사전 컴파일된 바이너리를 다운로드할 수 있습니다.
또는 다른 릴리스(일일 git 빌드를 위한 최신 메타 릴리스 포함)에 대한 GitHub 릴리스를 참조하세요.
현재 Apple Silicon용 공식 바이너리는 없지만 Visual Studio Code용 ShellCheck를 통해 타사 빌드를 사용할 수 있습니다.
Distro 패키지에는 이미 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에서 Raster 글꼴이 아닌 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
Shebang에서 지원하지 않는 기능을 사용할 때 ShellCheck가 경고합니다. 예를 들어 shebang을 #!/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를 사용하고 있는 건가?"라고 말하죠.
알렉산더 타라시코프(Alexander Tarasikov), 트위터를 통해
환경 변수, 명령줄을 통해 개별적으로 또는 파일 내에서 전역적으로 문제를 무시할 수 있습니다.
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 및 기여자.
즐거운 ShellChecking을 즐겨보세요!