بش اسکریپت که شل اسکریپت نیز نامیده میشود, یک زبان برنامه نویسی ساده و در عین حال جالب است که دستورات گنو/لینوکس را در یک فایل متنی توسط تعدادی syntax کنترل میکند. در این آموزش راجع به درک شل اسکرپیت, نحوهی ساخت فایل متنی, اجرایی کردن آن و آشنایی با اصطلاحات بش و کار با آنها صحبت میکنیم و باید بدانید این آموزش فقط گذری مختصر بر روی بش است.
شما باید ویرایشگری که با آن قصد برنامه نویسی را دارید انتخاب کنید که میتوانید از ویرایشگرهای تحت خط فرمان مانند vim و nano یا از ویرایشگرهای گرافیکی مانند gedit و atom استفاده کنید در قدم بعدی باید بدانید که از چه نسخهی بش استفاده میکنید برای این کار کافی است دستور زیر را در ترمینال وارد کنید :
bash $BASH_VERSION
که خروجی مانند زیر خواهد داشت :
[hossein@hossein ~]$ bash $BASH_VERSION bash: 4.3.42(1)-release
در حال حاضر آخرین نسخه ۴.۳.۴۲ میباشد پس از آپدیت بودن ورژن بش خود اطمینان حاصل فرمایید. اکنون نوبت به ساخت فایل متنی رسیده, هر اسکریپتی که نوشته میشود نسبت به زبان خود قالبی دارد برای مثال قالب اسکریپتهایی که با زبان پایتون نوشته میشوند py هستند, قالب فایلهای بش هم sh است اما شما میتوانید یک فایل متنی بدون هیچ قالبی درست کنید و سپس آن را مستقیم اجرا کنید که در ادامه راجع به آن صحبت میکنیم اکنون با دستور زیر یک فایل متنی ایجاد کنید :
touch name_of_your_file
به جای name_of_your_file کلمهای دیگر به عنوان نام اسکریپت بگذارید برای مثال من نام اسکریپت خود را pac میگذارم و ادامهی آموزش را طبق این نام پیش میبریم . تمام اسکریپتهایی که به زبان بش نوشته شدهاند با
#!/bin/bash
شروع میشوند پس در ابتدای فایل متنی خود باید این عبارت را بنویسید. هر چیزی که شما بعد از این عبارت بنویسید عملیاتی است که اسکریپت شما انجام میدهد برای مثال کلمهی echo برای نشان دادن یک عبارت یا نوشتن چیزی استفاده میشود و ما میتوانیم از آن در اسکریپت خود استفاده کنیم :
#!/bin/bash echo "Hello shell scripting!"
اسکریپت بالا باید Hello Shell Scripting را نشان دهد پس به آن اجازهی اجرا شدن میدهیم برای اینکار دستور زیر را وارد کنید :
sudo chmod u+x pac
اکنون ما به اسکریپت خود که pac نام داشت قابلیت اجرا شدن دادیم برای اینکه مطمئن شویم دستور ls -lthr را وارد میکنیم که خروجی آن مانند زیر خواهد بود :
[hossein@hossein ~]$ ls -lthr total 52K drwxrwxrwx 2 hossein users 4.0K Nov 4 21:45 Telegram drwxrwxrwx 2 hossein users 4.0K Nov 28 17:15 Templates drwxrwxrwx 2 hossein users 4.0K Nov 28 17:15 Public drwxrwxrwx 5 hossein users 4.0K Nov 29 16:51 Movies drwxrwxrwx 4 hossein users 4.0K Dec 2 17:12 VirtualBox VMs drwxrwxrwx 2 hossein users 4.0K Dec 2 17:41 Desktop -rwxrw-r-- 1 hossein users 1 Dec 3 16:37 pac drwxrwxrwx 4 hossein users 4.0K Dec 3 20:23 Pictures drwxrwxrwx 4 hossein users 4.0K Dec 4 06:38 Downloads drwxrwxrwx 2 hossein users 4.0K Dec 4 07:01 Videos drwxrwxrwx 4 hossein users 4.0K Dec 4 07:02 Music drwxrwxrwx 2 hossein users 4.0K Dec 4 07:09 Documents
همانطور که میبینید در خروجی بالا تمام محتویات خانه من را به اضافهی آن فایل pac نشان داده است در قسمتی که مربوط به دسترسیها میشود فایل pac حرف x که به معنی excute است را در سه حرف اول خود دارد پس فایل متنی pac را میشود به راحتی توسط کاربری که آن را اجرایی کرده با یکی دستورات زیر اجرا کرد :
sh pac
./pac
فایلهای شلی که توسط کاربر اجرایی نشدهاند با sh اجرا میشوند.
زمانی که اسکریپت را با یکی از دستورات بالا اجرا کردید باید خروجی مانند زیر داشته باشد :
[hossein@hossein ~]$ ./pac Hello Shell Scripting!
.
تبریک شما یاد گرفتید که یک اسکریپت خیلی سادهی بش چطوره نوشته و اجرا میشه !!!
.
اکنون وقت آن رسیده که با اصطلاحات و بعضی از سینتکسهای بش آشنا شوید و از آنها استفاده کنید به کد زیر دقت کنید :
display () { START=$(date +%s); FR_CNT=0; ETA=0; ELAPSED=0 while [ -e /proc/$PID ]; do sleep 1 VSTATS=$(tail -n1 "$RM"/ffmpeg-* | egrep -o 'frame=[0-9]+' | grep -Po 'd+' | tail -n1) if [ $VSTATS -gt $FR_CNT ] 2> /dev/null; then FR_CNT=$VSTATS PERCENTAGE=$(( 100 * FR_CNT / TOT_FR )) ELAPSED=$(( $(date +%s) - START )); echo $ELAPSED > /tmp/elapsed.value ETA=$(date -d @$(awk 'BEGIN{print int(('$ELAPSED' / '$FR_CNT') * ('$TOT_FR' - '$FR_CNT'))}') -u +%H:%M:%S) echo "# Working on file: $COUNT of $OF - Length: $DUR - Frames: $TOT_FR nFilename: ${NFILE%.*}nSaved to: $SAVEAS nRe-muxing with FFmpeg nFrame: $FR_CNT of $TOT_FR Elapsed: $(date -d @$ELAPSED -u +%H:%M:%S) ET to finish: $ETA" echo $PERCENTAGE fi done | zenity --progress --window-icon $ICON --title="Remuxing to $EXT" --text="Initializing please wait..." --percentage=0 --auto-close --auto-kill }
این کد قسمتی از یک اسکریپت است که در تابع display قرار دارد, تابع ها تقریبا در همهی زبانهای برنامه نویسی وجود دارند , در واقع تابعها برای مشخص کردن یک قسمت خاص از یک اسکریپت هستند که در صورتی که تابع با موفقیت کار خود را انجام داده باشد در ادامهی اسکریپت نیز فراخوانی میشوند البته این به مقصود برنامهنویس بستگی دارد که شرط اینکه اگر تابع با مشکل برخورد خروج کند را بگذارد !! در کل اگر بخواهم تابعها را در بش با یک جمله تعریف کنم باید بگویم تابعها پروسههای کوچکی در پروسهی اصلی هستند که موقع نیاز صدا زده میشوند !!
توابع در بش با علامت( } ) شروع و با ( { ) تمام میشوند. برای مثال این یک اسکریپت است که در آن از دو تابع استفاده شده :
#!/bin/bash function numbers { for i in {10..20} do echo $i done } function hello { echo hello } hello sleep 2 echo The numbers are : numbers exit
همانطور که در اسکریپت میبینید اسم یکی از تابعها number است که اعداد ۱۰ تا ۲۰ را میشمارد و تابع دیگری به نام hello که کلمهی hello را نشان میدهد وجود دارد و در ادامهی اسکریپت این دو تابع صدا شدهاند تا کار خود را انجام بدهند و خروجی زیر را تشکیل دادهاند :
[hossein@hossein ~]$ ./pac hello The numbers are : 10 11 12 13 14 15 16 17 18 19 20
آشنایی با شروط, حلقهها و Syntax ها :
if که در لغت به معنی اگر است و در بش نیز به کار میرود برای مثال برنامه نویسی یک پوسته گرافیکی ساده طراحی کرده است که نوشته که تحت بش است و کد زیر میگوید اگر کاربر در پوستهی گرافیکی پروسه را لغو کرد دیگر ادامه نده :
if [ $? = 1]; then exit fi
اما اگر این کد نباشد زمانی که کاربر با پوستهی گرافیکی لغو میکند پروسه به کار خودش ادامه میدهد و باید آن را دستی kill کرد. عبارتی که به عنوان شرط هست همیشه درون کروشه و جلوی if قرار دارد و همیشه در پایان حلقهی شرط باید از fi استفاده شود یک مثال دیگر :
#!/bin/bash pass="hossein" if [ "$pass" = "hossein" ] ; echo "That is okay !" then exit; fi
اسکریپت بالا گفته کلمهی (pass) مساوی است با (hossein) و بعد درون شرط گفته شده اگر (pass) مساوی بود با (hossein) جملهی (! That is okay) را نمایش بده و بعد خارج شو. یکی دیگر از عبارتهایی که در شل اسکریپت به کار میرود else است به اسکریپت زیر دقت کنید :
#!/bin/bash pass="arch" if [ "$pass" = "hossein" ] ; then echo "That is okay !" else echo "That is not okay :(" fi
در اسکریپت بالا مشخص کردیم که کلمهی (pass) مساوی است با (arch) و گفتیم اگر (pass) مساوی بود با (arch) بگو (That is okay) و اگر با (arch) مساوی نبود بگو( ): That is not okay) و خارج شو. اکنون این اسکریپت را اجرا میکنیم :
[hossein@hossein ~]$ ./pac That is not okay :(
همانطور که انتظار داشتیم خروجی جملهی (That is not okay) بود !!
شما میتوانید عملی را برای شرط دوم و سوم و .. با عبارت elif در نظر بگیرید, در بش هر جملهای که با علامت مربع (#) شروع شود یک Comment به حساب می آید و اجرا نمیشود, کامنتها معمولا اطلاعاتی راجع به اسکریپت میدهند. هر گاه شما در اسکریپت خود از عبارت sleep استفاده کنید نسبت به عدد بعد از آن باعث توقف موقت میشود, برای گرفتن داده از کاربر نیز میتوانید از عبارت read استفاده کنید حال با این تفاسیر اسکریپتی مینویسیم :
#!/bin/bash # this stupid scripts has been written by Hossein Heydari and its about password !! echo "What is the password ? " sleep 3 read pass if [ "$pass" = "hossein" ] ; then echo "That is okay !" elif [ "$pass" = "ubuntu" ] ; then echo " nice " else echo "That is not okay, " $pass " is not password :(" fi
این اسکریپت سوالی را با echo میپرسد و بعد ۳ ثانیه صبر میکند سپس منتظر گرفتن داده از کاربر میشود و نسبت به شرطهای تعیین شده ادامه میدهد. لطفا خودتان امتحانش کنید !!
یکی دیگر از حلقههای موجود (for) است, که توسط آن دو عبارت را به وسیلهی یک متغیر به هم دیگر مرتبط میکنند یا یک پروسه بسیار کوچک را در خودش نگه داری میکند یا میتوانیم از طریق آن یک ورودی بگیرم و روی آن تغییراتی ایجاد کنیم در کل حلقهی for کارایی های زیادی دارد برای مثال اسکریپتهای زیر را نگاه کنید :
for i in $( ls ) do echo $i > list done
این اسکریپت تمام محتویات موجود در خانه را در فایل متنی list/~ مینویسد یا اسکریپت زیر اعداد ۰ تا ۱۰۰ را ده تا ده تا میشمارد ! !
for boob in {0..100..10} do echo number $boob done
برای آشنایی بیشتر با حلقهی for میتوانید از این لینک استفاده نمایید. اکنون با چند سینتکس آشنا میشویم :
$۰ : نام فایل بش.
USER$ : کاربری که در حال حاضر اسکریپت را اجرا کرده.
= یا == : هر دو به معنی مساوی است.
?$ : وضعیت خروج از اسکریپت.
HOSTNAME$ : نام هاست کاربری که اسکریپت را اجرا کرده.
$$ : PID اسکریپت اجرا شده
variable$ : به جای variable متغیر قرار میگیرد در واقع هر حرف یا کلمهای که بعد از علامت دلار باشد و خودش یک سینتکس نباشد یک متغیر است برای مثال user$ یک متغیر است اما USER$ نیست.
حال با این تفاسیر اسکریپتی مینویسیم که از سینتکسهای بالا در آن استفاده شده باشد :
#!/bin/bash echo "name of this script is :" sleep 1 echo $0 sleep 1 echo "your user name is :" sleep 1 echo $USER sleep 1 echo "your host name is :" sleep 1 echo $HOSTNAME sleep 1 echo "should I kill this script ? yes or no " sleep 1 for i in * do read ans if [ "$ans" == "yes" ] ; then kill $$ elif [ "$ans" = "no" ] ; then echo "okay" sleep 1 echo "give a number ! " for pop in * do read pop expr $pop + 2 exit done else echo "Invalid Option ! Try again" fi done sleep 1 echo "give a number ! " for pop in * do read pop expr $pop + 2 exit done exit
اسکریپت را اجرا و نتیجهی آن را ببینید D:
.
قسمت اول این آموزش به پایان رسید قسمت دوم را هم به زودی با ویدیو ارائه میکنم توی قسمت دوم با حلقههای untill و while و همچنین عملیاتهای ریاضی در بش و …. صحبت میکنیم, فعلا یک ویدیو به زبان انگلیسی که تقریبا محتویات همین آموزش را درون اون قرار دادم در اینجا منتشر کردم میتونید ببینید.
یه چیز باحال در حال و هوای بش :