با اسکریپتنویسی در شل هم همانند کدنویسی در هر زبان برنامهنویسی دیگری ممکن است با یکسری باگ مواجه شویم. این باگها ممکن است به دلیل وجود اروری در اسکریپت همچون خطای سینتکسی، عدم وجود یک فایل مورد نیاز و یا عدم برخورداری از پرمیشنهای مورد نیاز برای عملی ساختن یک کامند ایجاد شوند.
بسیاری از ادمینهای حرفهای سیستمهای لینوکسی علاوه بر آشنایی با نحوهٔ اسکریپتنویسی، با استراتژیهای دیباگ کردن اسکریپتها نیز آشنا هستند به طوری که از دید برخی دولوپرها، تسط داشتن به مهارت دیباگینگ به مراتب مهمتر از مهارت اسکریپتنویسی است چرا که اسکریپتنویسی را هر کسی بلد است اما دیباگ کردن کاری است که از عهدهٔ هر دولوپری برنمیآید!
به طور کلی، پیش از اقدام کردن برای رفع ارورها، میبایست بدانیم که منبع ارور کجا است. در اسکریپتنویسی Bash، شما میتوانید با اجرای دستور bash –x ./script_file حالت Debug Mode (وضعیت دیباگینگ) را فعال نمایید و این در حالی است که فعال سازی این وضعیت به دلایل زیر کمک میکند تا بتوانید ریشهٔ مشکل را بیابید:
- هر کامندی قبل از اجرا نمایش داده میشود.
- قابلیت دیباگ کردن صرفاً بخشی از اسکریپت با استفاده از دستورات x- و x+ وجود دارد.
برای روشنتر شدن نحوهٔ دیباگ کردن یک اسکریپت در بش، فایلی تحت عنوان debug.sh ساخته و کدهای زیر را داخل آن مینویسیم:
#! /bin/bash
echo "Enter your title and fullname"
read name
echo "My title is ${name:0:2}"
echo "My fullname is ${name#*.}"
با توجه به آموزشهای قبلی، به نظر میرسد که دیگر نیازی به توضیح این که کدهای فوق چه کاری انجام میدهند نباشد. برای اجرای این اسکریپت، ابتدا با استفاده از دستور chmod +x debug.sh آن را اجرایی کرده سپس یک بار آن را تست میکنیم:
$ bash debug.sh
Enter your title and fullname
Mr. Behzad Moradi
My title is Mr
My fullname is Behzad Moradi
میبینیم که از Offset صفر تا دومین کاراکتر متغیر name برای نمایش لقب (Mr) استفاده شده و در خط بعد هم دستور دادهایم که هر آنچه پس از نقطه قرار گرفته به عنوان fullname (نام و نامخانوادگی) در نظر گرفته شود.
حال قصد داریم ببینیم که به چه شکل میتوانیم این اسکریپت را برای دیباگ کردن آماده سازیم؛ برای این منظور، کدهای فوق را به صورت زیر تغییر میدهیم:
#! /bin/bash
echo "Enter your title and fullname"
set -x
read name
echo "My title is ${name:0:2}"
echo "My fullname is ${name#*.}"
set +x
پیش از توضیح کدهای اضافه شدهٔ فوق، ابتدا اسکریپت را یک بار اجرا میکنیم:
$ bash debug.sh
Enter your title and fullname
+ read name
Mr. Behzad Moradi
+ echo 'My title is Mr'
My title is Mr
+ echo 'My fullname is Behzad Moradi'
My fullname is Behzad Moradi
+ set +x
همان طور که ملاحظه میشود، پس از نوشتن کامند set -x، خط به خط کدهای نوشته شده در اسکریپت که پس از کامند set -x قرار گرفتهاند به علاوهٔ نتیجهٔ آنها در معرض دید دولوپر قرار میگیرد که بدین شکل فرایند دیباگینگ برنامه به مراتب راحتتر خواهد شد.
ریدایرکت کردن ارورها به فایل
همان طور که در جدول زیر مشاهده میشود، تمامی برنامههایی که در یونیکس/لینوکس اجرا میشوند از ۳ اصطلاحاً File Stream برخوردار خواهند بود:
فایل استریم توضیحات نشانگر stdin ورودی استاندارد که به صورت پیشفرض کیبورد/ترمینال است. 0 stdout خروجی استاندارد که به صورت پیشفرض از طریق کامندلاین نمایش داده میشود. 1 stderr ارور استاندارد که پیامهای خطا نمایش داده شده یا ذخیره میشوند. 2
با استفاده از مفهومی تحت عنوان «ریدایرکت»، میتوانیم استریمها را در یک فایل و یا فایلهای مجزایی جهت تحلیل برنامه ذخیره سازیم.
برای روشنتر شدن کاربرد این استریمها، فایلی تحت عنوان error.sh ساخته و کدهای زیر را داخل آن مینویسیم:
#! /bin/bash
sum=0
for i in 1 2 3 4
do
sum=(($sum+$ir))
done
echo "The sum of $i numbers is: $sum"
پس از اجرایی کردن این فایل، یک بار آن را تست میکنیم:
$ bash error.sh
error.sh: line 5: syntax error near unexpected token `('
error.sh: line 5: ` sum=(($sum+$ir))'
error.sh: line 6: syntax error near unexpected token `done'
error.sh: line 6: `done'
با توجه به اینکه اسکریپت فوق حاوی مشکل است، تحت هیچ عنوان اجرا نخواهد شد و میبینیم که با ارور مواجه شدیم. حال قصد داریم دستور دهیم تا خروجی مرتبط با ارورها یا همان کد ۲ را در فایلی تحت عنوان error.txt ذخیره سازیم:
$ bash error.sh 2> error.txt
در واقع در کامند فوق با استفاده از <2 پس از bash error.sh دستور دادهایم که کلیهٔ ارورهای مرتبط با این اسکریپت در فایلی تحت عنوان error.txt ذخیره شوند (لازم به ذکر است با توجه به اینکه این فایل وجود خارجی ندارد، ابتدا ساخته شده سپس ارورها داخل آن ذخیره میشوند). حال در ادامه با استفاده از دستور cat که برای نمایش دادن محتویات فایلها است، محتویات ذخیره شده در فایل error.txt را نمایش میدهیم:
$ cat error.txt
error.sh: line 5: syntax error near unexpected token `('
error.sh: line 5: ` sum=(($sum+$ir))'
error.sh: line 6: syntax error near unexpected token `done'
error.sh: line 6: `done'
میبینیم همان ارورهایی که در حین اجرای برنامه در ترمینال نمایش داده میشدند، حال در فایل مرتبط با ارورها ذخیره شدهاند.