SHELLCHECK(1) General Commands Manual SHELLCHECK(1)

shellcheck - ابزار تحلیل و بررسی اسکریپت‌های شل

shellcheck [OPTIONS...] FILES...

ShellCheck یک ابزار تحلیل ایستا و لینتینگ (linting) برای اسکریپت‌های sh/bash است. تمرکز اصلی آن بر مدیریت خطاهای نحوی و دام‌های رایج در سطوح مبتدی و متوسط است، در شرایطی که شل تنها یک پیام خطای مبهم ارائه می‌دهد یا رفتار عجیبی از خود نشان می‌دهد؛ با این حال، برخی مشکلات پیشرفته‌تر را نیز گزارش می‌دهد که در آن‌ها حالت‌های خاص (corner cases) می‌توانند منجر به خرابی‌های دیرهنگام و مؤخر شوند.

ShellCheck توصیه‌های مختص به هر شل را ارائه می‌دهد. این خط را در نظر بگیرید:

(( area = 3.14*r*r ))
  • برای اسکریپت‌هایی که با #!/bin/sh شروع می‌شوند (یا هنگام استفاده از -s sh)، ShellCheck هشدار می‌دهد که (( .. )) با استاندارد POSIX سازگار نیست (مشابه checkbashisms).
  • برای اسکریپت‌هایی که با #!/bin/bash شروع می‌شوند (یا هنگام استفاده از -s bash)، ShellCheck هشدار می‌دهد که اعداد اعشاری پشتیبانی نمی‌شوند.
  • برای اسکریپت‌هایی که با #!/bin/ksh شروع می‌شوند (یا هنگام استفاده از -s ksh)، ShellCheck هیچ هشداری نمی‌دهد، زیرا ksh از اعداد اعشاری در محاسبات ریاضی پشتیبانی می‌کند.

هشدارها را در فایل‌های منبع‌شده (sourced) نیز صادر می‌کند. به‌طور معمول، shellcheck تنها دربارهٔ مشکلات موجود در فایل‌های مشخص‌شده هشدار می‌دهد. با این گزینه، هرگونه مشکل در فایل‌های فراخوانی‌شده (sourced) نیز گزارش خواهد شد.
برای خروجی TTY، رنگ‌ها را فعال می‌کند: always (همیشه)، never (هرگز) یا auto (خودکار). پیش‌فرض auto است. استفاده از --color بدون آرگومان معادل --color=always است.
صرفاً کدهای مشخص‌شده را به‌طور صریح در گزارش لحاظ می‌کند. گزینه‌های -i بعدی تجمعی هستند، اما همهٔ کدها را می‌توان یک‌جا به‌صورت جداشده با کاما در قالب یک آرگومان تعیین کرد. گزینه‌های لحاظ کردن (include) بر هرگونه گزینهٔ مستثنی کردن (exclude) ارائه‌شده اولویت دارند.
کدهای مشخص‌شده را به‌طور صریح از گزارش مستثنی می‌کند. گزینه‌های -e بعدی تجمعی هستند، اما همهٔ کدها را می‌توان یک‌جا به‌صورت جداشده با کاما در قالب یک آرگومان تعیین کرد.
فعال‌سازی/غیرفعال‌سازی تحلیل جریان داده (Dataflow Analysis) جهت شناسایی مشکلات بیشتر (پیش‌فرض true). اگر هنگام بررسی اسکریپت‌هایی با چندین هزار خط کد، ShellCheck از CPU/RAM بیش از حد استفاده کند، می‌توان تحلیل گسترده را با این پرچم یا یک دستورالعمل (directive) غیرفعال کرد. این پرچم بر دستورالعمل‌ها و فایل‌های rc اولویت دارد.
قالب خروجی shellcheck را مشخص می‌کند، که نتایج خود را در خروجی استاندارد چاپ می‌کند. گزینه‌های -f بعدی نادیده گرفته می‌شوند؛ برای اطلاعات بیشتر بخش FORMATS را در ادامه ببینید.
فهرستی از بررسی‌های اختیاری شناخته‌شده را در خروجی نمایش می‌دهد. این موارد را می‌توان با پرچم‌های -o یا دستورالعمل‌های enable فعال کرد.
برای یافتن فایل‌های پیکربندی .shellcheckrc جستجو نمی‌کند.
فایل پیکربندی مشخص‌شده را به جستجوی آن در مکان‌های پیش‌فرض ترجیح می‌دهد.
بررسی‌های اختیاری را فعال می‌کند. نام ویژهٔ all همهٔ آن‌ها را فعال می‌کند. گزینه‌های -o بعدی تجمیع می‌شوند. این عمل معادل تعیین دستورالعمل‌های enable است.
مسیرهای جستجوی فایل‌های منبع‌شده (sourced) را مشخص می‌کند که در یونیکس با : و در ویندوز با ; از هم جدا می‌شوند. این عمل معادل تعیین دستورالعمل‌های search-path است.
لهجهٔ شل Bourne را مشخص می‌کند. مقادیر معتبر عبارتند از sh، bash، dash، ksh و busybox. حالت پیش‌فرض بر این است که شل از روی دستورالعمل shell فایل، شِبانگ (shebang)، یا پسوند .bash/.bats/.dash/.ksh (به همین ترتیب) استنتاج شود. sh به sh در استاندارد POSIX اشاره دارد (نه شل سیستم)، و دربارهٔ مشکلات انتقال‌پذیری و سازگاری هشدار می‌دهد.
حداقل سطح شدت (severity) خطاها را برای بررسی مشخص می‌کند. مقادیر معتبر به ترتیب شدت عبارتند از error، warning، info و style. پیش‌فرض style است.
اطلاعات نسخه را چاپ کرده و خارج می‌شود.
برای خروجی TTY، تعداد NUM پیوند ویکی برای اطلاعات بیشتر دربارهٔ هشدارهای ذکرشده نمایش می‌دهد. برای غیرفعال کردن کامل آن‌ها، مقدار را برابر با 0 قرار دهید.
دستورهای source را حتی در صورتی که فایل به عنوان ورودی مشخص نشده باشد دنبال می‌کند. به‌طور پیش‌فرض، shellcheck فقط فایل‌های مشخص‌شده در خط فرمان (به‌علاوهٔ /dev/null) را دنبال می‌کند. این گزینه امکان دنبال کردن هر فایلی را که اسکریپت ممکن است source کند، فراهم می‌سازد.

این گزینه را همچنین می‌توان با استفاده از external-sources=true در .shellcheckrc فعال کرد. این پرچم اولویت دارد.

یک یا چند فایل اسکریپت جهت بررسی، یا "-" برای ورودی استاندارد..SH "قالب‌ها (FORMATS)"
خروجی متنی ساده و خوانا برای انسان. این حالت پیش‌فرض است.
خروجی سازگار با GCC. برای ویرایشگرهایی که از کامپایل و نمایش خطاهای نحوی پشتیبانی می‌کنند مفید است.

برای مثال، در Vim، دستور :set makeprg=shellcheck\ -f\ gcc\ % امکان استفاده از :make را برای بررسی اسکریپت، و :cnext را برای پرش به خطای بعدی فراهم می‌کند.

<file>:<line>:<column>: <type>: <message>
خروجی XML سازگار با Checkstyle. به‌صورت مستقیم یا از طریق افزونه‌ها توسط بسیاری از IDEها و سامانه‌های پایش ساخت پشتیبانی می‌شود.
<?xml version='1.0' encoding='UTF-8'?>
<checkstyle version='4.3'>
  <file name='file'>
    <error
      line='line'
      column='column'
      severity='severity'
      message='message'
      source='ShellCheck.SC####' />
    ...
  </file>
  ...
</checkstyle>
اصلاحات خودکار در قالب unified diff. می‌تواند به git apply یا patch -p1 لوله‌کشی (pipe) شود تا اصلاحات به‌طور خودکار اعمال گردند.
--- a/test.sh
+++ b/test.sh
@@ -2,6 +2,6 @@
 ## Example of a broken script.
 for f in $(ls *.m3u)
 do
-  grep -qi hq.*mp3 $f \
+  grep -qi hq.*mp3 "$f" \
     && echo -e 'Playlist $f contains a HQ file in mp3 format'
 done
فرمت Json یک قالب سریال‌سازی محبوب است که برای برنامه‌های کاربردی وب مناسب‌تر است. قالب json در ShellCheck فشرده است و تنها شامل حداقل اطلاعات لازم است. تب‌ها (Tabs) به عنوان ۱ نویسه شمارش می‌شوند.
{
  comments: [
    {
      "file": "filename",
      "line": lineNumber,
      "column": columnNumber,
      "level": "severitylevel",
      "code": errorCode,
      "message": "warning message"
    },
    ...
  ]
}
این یک نسخه قدیمی (legacy) از قالب json1 است. یک آرایه خام از پیام‌ها (comments) است و تمامی فاصله‌ها دارای توقف تب (tab stop) به اندازه ۸ هستند.
فرونشانی تمام خروجی‌های عادی. در صورتی که هیچ مشکلی یافت نشود با کد صفر خارج می‌شود، در غیر این صورت با یک خارج می‌شود. پردازش پس از یافتن نخستین مشکل متوقف می‌شود..SH "دستورالعمل‌ها (DIRECTIVES)" دستورالعمل‌های ShellCheck می‌توانند به صورت کامنت در اسکریپت شل مشخص شوند. اگر پیش از نخستین دستور قرار گیرند، در سطح سراسر فایل (file-wide) در نظر گرفته می‌شوند. در غیر این صورت، بر روی دستور یا بلوک بلافاصله پس از خود اعمال می‌شوند:
# shellcheck key=value key=value
command-or-structure

برای نمونه، برای نادیده گرفتن SC2035 درباره استفاده از ./*.jpg:

# shellcheck disable=SC2035
echo "Files: " *.jpg

برای مشخص کردن محل جستجوی فایلی که در غیر این صورت به صورت پویا تعیین می‌شد در ShellCheck:

# shellcheck source=./lib.sh
source "$(find_install_dir)/lib.sh"

در اینجا از یک گروه آکولاد (brace group) شل برای نادیده گرفتن یک هشدار در چندین خط استفاده شده است:

# shellcheck disable=SC2016
{
  echo 'Modifying $PATH'
  echo 'PATH=foo:$PATH' >> ~/.bashrc
}

کلیدهای معتبر عبارتند از:

فهرستی از کدهای خطای جدا شده با کاما را برای دستور بعدی غیرفعال می‌کند. این دستور می‌تواند یک دستور ساده مانند echo foo یا یک دستور مرکب مانند تعریف تابع، بلوک subshell یا حلقه باشد. یک بازه را می‌توان با خط تیره مشخص کرد، مانند disable=SC3000-SC4000 برای مستثنی کردن 3xxx. همه هشدارها را می‌توان با disable=all غیرفعال کرد.
یک بررسی اختیاری را با نام، همان‌گونه که با --list-optional فهرست شده است، فعال می‌کند. تنها دستورالعمل‌های enable در سطح کل فایل در نظر گرفته می‌شوند.
تنظیم روی true/false برای فعال/غیرفعال کردن تحلیل جریان داده (dataflow analysis). مشخص کردن # shellcheck extended-analysis=false در اسکریپت‌های بزرگِ به طور خودکار تولیدشده (بیش از ۲۰۰۰ خط)، مصرف منابع ShellCheck را به بهای صرف‌نظر از برخی بررسی‌ها کاهش می‌دهد. تحلیل گسترده به طور پیش‌فرض فعال است.
تنظیم روی true در .shellcheckrc تا به ShellCheck همیشه اجازه داده شود فایل‌های دلخواه را از عبارات 'source' باز کند (همان روشی که بیشتر ابزارها عمل می‌کنند).
این گزینه تنها به دلیل پیشینه ShellCheck به عنوان یک سرویس از راه دور برای بررسی اسکریپت‌های غیرقابل اعتماد، به طور پیش‌فرض روی false است. می‌توان آن را با خیال راحت برای فرایند توسعه عادی فعال کرد.
نام فایل واردشده توسط عبارت source/. را بازنویسی می‌کند. از این گزینه می‌توان برای تعیین محل فایلی که نامش در زمان اجرا مشخص می‌شود استفاده کرد، یا با هدایت آن به استفاده از /dev/null، از یک فراخوانی منبع صرف‌نظر کرد.
یک دایرکتوری را به مسیر جستجو برای عبارات source/. اضافه می‌کند (به طور پیش‌فرض، فقط دایرکتوری کاری ShellCheck در نظر گرفته می‌شود). مسیرهای مطلق نیز بر مبنای این مسیرها ریشه‌بندی خواهند شد. مسیر ویژه SCRIPTDIR می‌تواند برای تعیین دایرکتوری اسکریپت در حال بررسی استفاده شود، مانند source-path=SCRIPTDIR یا source-path=SCRIPTDIR/../libs. مسیرهای متعدد با یکدیگر تجمیع می‌شوند و -P نسبت به آن‌ها تقدم دارد.
شل شناسایی‌شده از shebang را بازنویسی می‌کند. این گزینه برای فایل‌هایی که قرار است فراخوانی شوند (و در نتیجه فاقد shebang هستند)، یا احتمالاً به عنوان یک جایگزین هدفمندتر برای 'disable=SC2039'، مفید است..SH "فایل‌های پیکربندی (RC FILES)" مگر اینکه از --norc استفاده شود، ShellCheck به دنبال فایلی به نام .shellcheckrc یا shellcheckrc در دایرکتوری اسکریپت و تک‌تک دایرکتوری‌های والد آن خواهد گشت. در صورت یافتن، جفت‌های key=value را از آن خوانده و با آن‌ها به‌عنوان دستورالعمل‌های سراسری برای کل فایل رفتار خواهد کرد.

در اینجا نمونه‌ای از .shellcheckrc آورده شده است:

# Look for 'source'd files relative to the checked script,
# and also look for absolute paths in /mnt/chroot
source-path=SCRIPTDIR
source-path=/mnt/chroot
# Since 0.9.0, values can be quoted with '' or "" to allow spaces
source-path="My Documents/scripts"
# Allow opening any 'source'd file, even if not specified as input
external-sources=true
# Turn on warnings for unquoted variables with safe values
enable=quote-safe-variables
# Turn on warnings for unassigned uppercase variables
enable=check-unassigned-uppercase
# Allow [ ! -z foo ] instead of suggesting -n
disable=SC2236

اگر هیچ .shellcheckrcی در هیچ‌یک از دایرکتوری‌های والد پیدا نشود، ShellCheck به دنبال ~/.shellcheckrc و در ادامه $XDG_CONFIG_HOME (معمولاً ~/.config/shellcheckrc) در یونیکس، یا %APPDATA%/shellcheckrc در ویندوز خواهد گشت. تنها نخستین فایلِ یافت‌شده استفاده خواهد شد.

نکته برای کاربران Snap: محیط ایزوله (Sandbox) اسنپ اجازه دسترسی به فایل‌های پنهان را نمی‌دهد. به جای آن از shellcheckrc بدون نقطه استفاده کنید.

نکته برای کاربران Docker: نرم‌افزار ShellCheck تنها قادر است به دنبال فایل‌هایی بگردد که در کانتینر سوار (mount) شده‌اند، بنابراین ~/.shellcheckrc خوانده نخواهد شد.

متغیر محیطی SHELLCHECK_OPTS می‌تواند با پرچم‌های پیش‌فرض تنظیم شود:

export SHELLCHECK_OPTS='--shell=bash --exclude=SC2016'

مقدار آن بر اساس فاصله‌ها تفکیک شده و در هر بار فراخوانی، به ابتدای خط فرمان اضافه خواهد شد.

ابزار ShellCheck از کدهای خروج زیر استفاده می‌کند:

  • 0: تمامی فایل‌ها با موفقیت و بدون هیچ مشکلی پویش شدند.
  • 1: تمامی فایل‌ها با موفقیت پویش شدند، اما مشکلاتی وجود داشت.
  • 2: برخی از فایل‌ها قابل پردازش نبودند (برای نمونه، فایل پیدا نشد).
  • 3: برنامه ShellCheck با نحو نادرست فراخوانی شد (برای نمونه، پرچم ناشناخته).
  • 4: برنامه ShellCheck با گزینه‌های نادرست فراخوانی شد (برای نمونه، فرمتر ناشناخته).

این نگارش از ShellCheck تنها به زبان انگلیسی موجود است. تمامی فایل‌ها با تساهل به صورت UTF-8 رمزگشایی می‌شوند و در صورت وجود توالی‌های نامعتبر، از ISO-8859-1 به عنوان جایگزین استفاده می‌شود. متغیر LC_CTYPE برای خروجی لحاظ می‌شود و برای لوکال‌هایی که کدگذاری در آن‌ها نامشخص است (مانند لوکال C)، پیش‌فرض روی UTF-8 است.

کاربران ویندوز که خطای commitBuffer: invalid argument (invalid character) را مشاهده می‌کنند، باید ترمینال خود را با دستور chcp 65001 برای استفاده از UTF-8 تنظیم کنند.

(اگر مطالب این بخش نامفهوم به نظر می‌رسند، به احتمال زیاد تحت تأثیر آن قرار نخواهید گرفت)

برای جلوگیری از پیشنهادهای گیج‌کننده و نادرست، ShellCheck الزام می‌کند که بدنه توابع یا { brace groups; } باشند یا ( subshells )، و نام‌های توابعی که شامل []*=! هستند تنها پس از کلیدواژه function شناخته می‌شوند.

تعریف‌های غیرمتعارف زیر برای توابع در Bash یکسان هستند، اما ShellCheck تنها دومی را به رسمیت می‌شناسد.

[x!=y] () [[ $1 ]]
function [x!=y] () { [[ $1 ]]; }

پوسته‌های فاقد کلیدواژه function از ابتدا اجازه استفاده از این نویسه‌ها را در نام توابع نمی‌دهند. نام‌های توابعی که شامل {} باشند به‌هیچ‌وجه پشتیبانی نمی‌شوند.

افزون بر این، اگر ShellCheck عبارت [x!=y] را ببیند، فرض خواهد کرد که این یک مقایسه نامعتبر است. برای فراخوانی تابع بالا، دستور را مانند '[x!=y]' نقل‌قول کنید، یا برای حفظ همان رفتار تطبیق الگو (globbing)، از command [x!=y] استفاده نمایید.

ابزار ShellCheck محدودیت‌های بیشتری را بر دستور [ اعمال می‌کند تا به عیب‌یابی موارد استفاده نامعتبر و رایج کمک کند. اگرچه [ $x= 1 ] در استاندارد POSIX تعریف شده است، ShellCheck فرض خواهد کرد که مقصود، مقایسه بسیار محتمل‌ترِ [ "$x" = 1 ] بوده و بر این اساس با خطا متوقف می‌شود. برای کاربردهای غیرمعمول یا پویای دستور [، به جای آن از test یا \[ استفاده کنید..SH "گزارش باگ‌ها (REPORTING BUGS)" باگ‌ها و مشکلات را می‌توان در GitHub گزارش کرد:

https://github.com/koalaman/shellcheck/issues

ShellCheck توسط Vidar Holen و با یاری فهرستی طولانی از مشارکت‌کنندگان فوق‌العاده توسعه یافته و نگهداری می‌شود.

کپی‌رایت 2012-2025، Vidar Holen و مشارکت‌کنندگان. تحت مجوز GNU General Public License نسخه 3 یا بالاتر، ببینید: https://gnu.org/licenses/gpl.html

sh(1), bash(1), dash(1), ksh(1)

ابزار تحلیل اسکریپت‌های شل