ShellCheck เป็นเครื่องมือ GPLv3 ที่ให้คำเตือนและคำแนะนำสำหรับเชลล์สคริปต์ bash/sh:
เป้าหมายของ ShellCheck คือ
เพื่อชี้ให้เห็นและชี้แจงปัญหาไวยากรณ์ของผู้เริ่มต้นทั่วไปที่ทำให้เชลล์แสดงข้อความแสดงข้อผิดพลาดที่เป็นความลับ
เพื่อชี้ให้เห็นและชี้แจงปัญหาความหมายระดับกลางทั่วไปที่ทำให้เชลล์มีพฤติกรรมแปลก ๆ และตอบโต้โดยสัญชาตญาณ
เพื่อชี้ให้เห็นคำเตือนที่ละเอียดอ่อน กรณีมุม และข้อผิดพลาดที่อาจทำให้สคริปต์การทำงานของผู้ใช้ขั้นสูงล้มเหลวในสถานการณ์ในอนาคต
ดูแกลเลอรีโค้ดที่ไม่ถูกต้องเพื่อดูตัวอย่างสิ่งที่ ShellCheck สามารถช่วยคุณระบุได้!
มีหลายวิธีในการใช้ ShellCheck!
วางเชลล์สคริปต์บน https://www.shellcheck.net เพื่อรับคำติชมทันที
ShellCheck.net จะซิงโครไนซ์กับคอมไพล์ล่าสุดเสมอ และเป็นวิธีที่ง่ายที่สุดในการทดลองใช้ ShellCheck บอกเพื่อนของคุณ!
รัน shellcheck yourscript
ในเทอร์มินัลของคุณเพื่อส่งออกทันทีดังที่แสดงด้านบน
คุณสามารถดูคำแนะนำของ ShellCheck ได้โดยตรงในโปรแกรมแก้ไขต่างๆ
-
-
ประเสริฐ ผ่าน 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 แบบธรรมดา, XML ที่เข้ากันได้กับ CheckStyle, คำเตือนที่เข้ากันได้กับ GCC รวมถึงข้อความที่มนุษย์อ่านได้ (มีหรือไม่มีสี ANSI) ดูหน้าวิกิการรวมสำหรับเอกสารเพิ่มเติม
วิธีที่ง่ายที่สุดในการติดตั้ง ShellCheck ในเครื่องคือผ่านตัวจัดการแพ็คเกจของคุณ
บนระบบที่มี Cabal (ติดตั้งไปที่ ~/.cabal/bin
):
cabal update
cabal install ShellCheck
บนระบบที่มี Stack (ติดตั้งเป็น ~/.local/bin
):
stack update
stack install ShellCheck
บน distros ที่ใช้ Debian:
sudo apt install shellcheck
บน distros ที่ใช้ Arch Linux:
pacman -S shellcheck
หรือรับเชลล์เช็คบินอิสระจาก AUR
บน distros ที่ใช้ Gentoo:
emerge --ask shellcheck
บน distros ที่ใช้ EPEL:
sudo yum -y install epel-release
sudo yum install ShellCheck
บน distros ที่ใช้ Fedora:
dnf install ShellCheck
บน FreeBSD:
pkg install hs-ShellCheck
บน macOS (OS X) ด้วย Homebrew:
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 (ผ่านช็อคโกแลต):
C: > choco install shellcheck
หรือ Windows (ผ่าน winget):
C: > winget install --id koalaman.shellcheck
หรือ Windows (ผ่านสกู๊ป):
C: > scoop install shellcheck
จากคอนดาฟอร์จ:
conda install -c conda-forge shellcheck
จากสแน็ปสโตร์:
snap install --channel=edge shellcheck
จากนักเทียบท่าฮับ:
docker run --rm -v " $PWD :/mnt " koalaman/shellcheck:stable myscript
# Or :v0.4.7 for that version, or :latest for daily builds
หรือใช้ koalaman/shellcheck-alpine
หากคุณต้องการขยายรูปภาพที่ใช้ Alpine Linux ที่ใหญ่กว่า มันทำงานเหมือนกับอิมเมจ Alpine ทั่วไปทุกประการ แต่มีการติดตั้ง Shellcheck ไว้ล่วงหน้าแล้ว
การใช้ตัวจัดการแพ็คเกจ nix:
nix-env -iA nixpkgs.shellcheck
การใช้ตัวจัดการแพ็คเกจ Flox
flox install shellcheck
หรือคุณสามารถดาวน์โหลดไบนารีที่คอมไพล์ไว้ล่วงหน้าสำหรับรุ่นล่าสุดได้ที่นี่:
หรือดู GitHub Releases สำหรับรุ่นอื่นๆ (รวมถึง meta-release ล่าสุดสำหรับรุ่น git รายวัน)
ขณะนี้ไม่มีไบนารีอย่างเป็นทางการสำหรับ Apple Silicon แต่บิลด์ของบุคคลที่สามมีให้บริการผ่าน ShellCheck สำหรับ Visual Studio Code
แพ็คเกจ Distro มาพร้อมกับ man
page แล้ว หากคุณกำลังสร้างจากแหล่งที่มา สามารถติดตั้งได้ด้วย:
pandoc -s -f markdown-smart -t man shellcheck.1.md -o shellcheck.1
sudo mv shellcheck.1 /usr/share/man/man1
หากต้องการรัน ShellCheck ผ่านการคอมมิตล่วงหน้า ให้เพิ่ม hook ลงใน .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 และต้องใช้ RAM 2GB เพื่อคอมไพล์
ShellCheck สร้างและบรรจุโดยใช้ Cabal ติดตั้งแพ็คเกจ cabal-install
จากตัวจัดการแพ็คเกจของระบบของคุณ (เช่น apt-get
, brew
, emerge
, yum
หรือ zypper
)
บน macOS (OS X) คุณสามารถติดตั้ง Cabal ได้อย่างรวดเร็วโดยใช้ Brew ซึ่งใช้เวลาสองสามนาทีแทนที่จะใช้เวลานานกว่า 30 นาทีหากคุณพยายามคอมไพล์จากแหล่งที่มา
$ brew install cabal-install
บน MacPorts แพ็คเกจจะเรียกว่า hs-cabal-install
แทน ในขณะที่ผู้ใช้ Windows ดั้งเดิมควรติดตั้งแพลตฟอร์ม Haskell เวอร์ชันล่าสุดจากhttps://www.haskell.org/platform/
ตรวจสอบว่ามีการติดตั้ง cabal
และอัปเดตรายการการพึ่งพาด้วย
$ cabal update
git clone
ที่เก็บนี้ และ cd
ไปยังไดเร็กทอรีต้นทาง ShellCheck เพื่อสร้าง/ติดตั้ง:
$ 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 ไม่ใช่แบบอักษร Raster และตั้งค่าเพจรหัสที่ใช้งานเป็น UTF-8 (65001) ด้วย chcp
:
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 จะเตือนเมื่อใช้คุณสมบัติที่ Shebang ไม่รองรับ ตัวอย่างเช่น หากคุณตั้งค่า 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 อยู่เหรอ"
อเล็กซานเดอร์ ทาราซิคอฟ ทวิตเตอร์
สามารถละเว้นปัญหาได้ผ่านทางตัวแปรสภาพแวดล้อม บรรทัดคำสั่ง ทีละรายการหรือทั่วโลกภายในไฟล์:
https://github.com/koalaman/shellcheck/wiki/Ignore
โปรดใช้ตัวติดตามปัญหา GitHub สำหรับข้อบกพร่องหรือข้อเสนอแนะคุณสมบัติ:
https://github.com/koalaman/shellcheck/issues
โปรดส่งแพตช์ไปยังโค้ดหรือเอกสารประกอบตามคำขอดึง GitHub! ตรวจสอบ DevGuide บน ShellCheck Wiki
ผลงานจะต้องได้รับอนุญาตภายใต้ GNU GPLv3 ผู้ร่วมให้ข้อมูลยังคงรักษาลิขสิทธิ์
ShellCheck ได้รับอนุญาตภายใต้ GNU General Public License, v3. สำเนาของใบอนุญาตนี้จะรวมอยู่ในไฟล์ LICENSE
ลิขสิทธิ์ 2012-2019, Vidar 'koala_man' Holen และผู้มีส่วนร่วม
ขอให้มีความสุขในการตรวจสอบเชลล์!