آموزش جامع اسکریپت نویسی بش (Bash scripting) در کالی لینوکس

در این آموزش، شما خواهید دید که چگونه می‌توانید دستورات اسکریپتی را با استفاده از Bash ایجاد کنید. چرا Bash scripting؟ جهانی بودن Bash به ما، تستر های نفوذ، این امکان را می‌دهد که دستورات قدرتمند ترمینال را بدون نیاز به نصب یک کامپایلر یا یک integrated development environment (IDE) اجرا کنیم. برای توسعه یک Bash script، تنها چیزی که نیاز دارید یک ویرایشگر متن است و شما آماده‌اید. کی از Bash scripts استفاده کنیم؟ این سوال مهمی است که باید قبل از شروع این فصل به آن پرداخته شود! Bash برای توسعه ابزارهای پیچیده طراحی نشده است. اگر قصد دارید چنین کاری انجام دهید، بهتر است از Python استفاده کنید (مفاهیم ابتدایی Python در بخش‌های بعدی این کتاب پوشش داده شده است).

Bash برای ابزارهای کوچک و سریع است که زمانی که بخواهید زمان صرفه‌جویی کنید به کار می‌رود (برای مثال، برای جلوگیری از تکرار دستورات یکسان، آن‌ها را در یک Bash script می‌نویسید). این فصل نه تنها زبان Bash scripting را به شما آموزش می‌دهد، بلکه فراتر از آن، ایدئولوژی برنامه‌نویسی را نیز به شما نشان می‌دهد. اگر شما به تازگی وارد دنیای برنامه‌نویسی شده‌اید، این فصل نقطه شروع خوبی برای شماست تا درک کنید که زبان‌های برنامه‌نویسی چگونه کار می‌کنند (آن‌ها شباهت‌های زیادی دارند).

در این فصل، شما خواهید آموخت:

■ Printing to the screen using Bash
■ Using variables
■ Using script parameters
■ Handling user input
■ Creating functions
■ Using conditional if statements
■ Using while and for loops

Basic Bash Scripting

Figure 2.1 تمامی دستورات را خلاصه کرده است، بنابراین می‌توانید از آن به عنوان مرجع برای درک تمامی محتوای این فصل استفاده کنید. به طور خلاصه، basic Bash scripting به دسته‌های زیر تقسیم می‌شود:

■ Variables
■ Functions
■ User input
■ Script output
■ Parameters

Printing to the Screen in Bash

دو روش رایج برای نوشتن در خروجی خط فرمان ترمینال با استفاده از Bash scripting وجود دارد. روش اول ساده استفاده از دستور echo است که در فصل قبلی دیدیم (ما مقدار متن را در داخل کوتیشن‌های تکی یا دوتایی قرار می‌دهیم):

$echo 'message to print.'

روش دوم دستور printf است؛ این دستور از echo انعطاف‌پذیرتر است زیرا به شما این امکان را می‌دهد که رشته‌ای که می‌خواهید چاپ کنید را قالب‌بندی کنید:

$printf 'message to print'

فرمول قبلی خیلی ساده است؛ در واقع، printf به شما این امکان را می‌دهد که رشته‌ها را به خوبی قالب‌بندی کنید (نه فقط برای چاپ؛ این بیشتر از آن است). بیایید یک مثال ببینیم:
اگر بخواهیم تعداد میزبان‌های زنده در یک شبکه را نمایش دهیم، می‌توانیم از الگوی زیر استفاده کنیم:

root@kali:~# printf "%s %d\n" "Number of live hosts:" 15
Number of live hosts: 15

بیایید دستور را تقسیم کنیم تا بهتر متوجه شوید که چه اتفاقی می‌افتد:

%s: یعنی ما یک رشته (متن) را در این موقعیت وارد می‌کنیم
%d: یعنی یک عدد صحیح (عدد اعشاری) را در این موقعیت وارد می‌کنیم
\n: یعنی پس از چاپ، می‌خواهیم به خط جدید برویم

همچنین توجه کنید که ما از کوتیشن‌های دوتایی به جای کوتیشن‌های تکی استفاده می‌کنیم. کوتیشن‌های دوتایی به ما این امکان را می‌دهند که انعطاف بیشتری در دستکاری رشته‌ها نسبت به کوتیشن‌های تکی داشته باشیم. بنابراین، بیشتر مواقع می‌توانیم از کوتیشن‌های دوتایی برای printf استفاده کنیم (به ندرت نیاز به استفاده از کوتیشن‌های تکی داریم). برای قالب‌بندی یک رشته با استفاده از دستور printf، می‌توانید از الگوهای زیر استفاده کنید:

%s: رشته (متن‌ها)
%d: عدد صحیح (اعداد)
%f: اعشاری (شامل اعداد مثبت و منفی)
%x: هگزادسیمال
\n: خط جدید
\r: بازگشت به ابتدای خط
\t: تب افقی

 Variables

متغیر چیست و چرا هر زبان برنامه‌نویسی از آن استفاده می‌کند؟ یک متغیر را به عنوان یک منطقه ذخیره‌سازی در نظر بگیرید که می‌توانید مقادیری مانند رشته‌ها و اعداد را در آن ذخیره کنید. هدف این است که از آن‌ها به طور مکرر در برنامه خود استفاده کنید، و این مفهوم برای هر زبان برنامه‌نویسی اعمال می‌شود (فقط مختص Bash scripting نیست).برای اعلام یک متغیر، باید نام و مقدار آن را مشخص کنید (مقدار به طور پیش‌فرض یک رشته است). نام متغیر فقط می‌تواند شامل یک کاراکتر الفبایی یا خط زیر (_) باشد (در سایر زبان‌های برنامه‌نویسی کنوانسیون‌های نام‌گذاری متفاوتی وجود دارد).

برای مثال، اگر بخواهید آدرس IP روتر را در یک متغیر ذخیره کنید، ابتدا یک فایل به نام var.sh ایجاد می‌کنید (فایل‌های Bash script با .sh تمام می‌شوند)، و داخل فایل، کد زیر را وارد می‌کنید:

#!/bin/bash  
#Simple program with a variable  
ROUTERIP="10.0.0.1"  
printf "The router IP address: $ROUTERIP\n"

توضیح اولین فایل Bash script شما:

#!/bin/bash به نام Bash shebang شناخته می‌شود؛ ما باید آن را در ابتدا قرار دهیم تا به Kali Linux بگوییم که از چه مفسری برای تجزیه فایل اسکریپت استفاده کند (ما از همین مفهوم در فصل 18، “Pentest Automation with Python”، با زبان برنامه‌نویسی Python استفاده خواهیم کرد). # در خط دوم برای نشان دادن این است که این یک کامنت است (کامنت‌ها دستوراتی هستند که نویسنده داخل کد یا اسکریپت برای مرجع بعدی می‌گذارد).
■ نام متغیر ROUTERIP است و مقدار آن 10.0.0.1 است.
■ در نهایت، ما از تابع printf برای چاپ مقدار به صفحه خروجی استفاده می‌کنیم.

برای اجرای آن، ابتدا مطمئن شوید که مجوزهای لازم را به آن داده‌اید (به خروجی زیر نگاه کنید تا ببینید اگر این کار را نکنید چه اتفاقی می‌افتد). از آنجایی که ما در همان دایرکتوری (/root) هستیم، از ./var.sh برای اجرای آن استفاده خواهیم کرد:

root@kali:~# ./var.sh  
bash: ./var.sh: Permission denied  
root@kali:~# chmod +x var.sh  
root@kali:~# ./var.sh   
The router IP address: 10.0.0.1 

تبریک می‌گوییم، شما اولین Bash script خود را ساختید! حالا فرض کنید می‌خواهیم این اسکریپت به طور خودکار اجرا شود بدون اینکه نیاز به مشخص کردن مسیر آن در سیستم داشته باشیم. برای این کار، باید آن را به متغیر $PATH اضافه کنیم. در مورد ما، ما /opt را به متغیر $PATH اضافه خواهیم کرد تا بتوانیم اسکریپت‌های شخصی خود را در این دایرکتوری ذخیره کنیم. ابتدا فایل .bashrc را با استفاده از هر ویرایشگر متنی باز کنید. پس از بارگذاری فایل، به پایین بروید و خطی که در شکل 2.2 برجسته شده است را اضافه کنید.


تغییرات باعث می‌شود که /opt به متغیر $PATH اضافه شود. در این مرحله، فایل را ذخیره کرده و تمام ترمینال‌ها را ببندید. دوباره پنجره ترمینال را باز کنید و فایل اسکریپت را به پوشه /opt کپی کنید. از این پس، نیازی به وارد کردن مسیر آن نیست؛ فقط با تایپ نام اسکریپت var.sh آن را اجرا می‌کنیم (دیگر نیازی به اجرای دوباره chmod نیست؛ مجوز اجرا قبلاً تنظیم شده است):

root@kali:~# cp var.sh /opt/  
root@kali:~# cd /opt  
root@kali:/opt# ls -la | grep "var.sh"  
-rwxr-xr-x 1 root root 110 Sep 28 11:24 var.sh  
root@kali:/opt# var.sh  
The router IP address: 10.0.0.1

 Commands Variable

گاهی اوقات ممکن است بخواهید دستورات را اجرا کنید و خروجی آن‌ها را در یک متغیر ذخیره کنید. بیشتر اوقات هدف این است که محتوای خروجی دستور را دستکاری کنید. در اینجا یک دستور ساده داریم که دستور ls را اجرا می‌کند و نام فایل‌هایی را که کلمه “simple” در آن‌ها وجود دارد با استفاده از دستور grep فیلتر می‌کند. (نگران نباشید، سناریوهای پیچیده‌تری را در بخش‌های بعدی این فصل خواهید دید. در حال حاضر، بر روی اصول تمرکز کنید و تمرین کنید).

#!/bin/bash  
LS_CMD=$(ls | grep 'simple')  
printf "$LS_CMD\n"

نتایج اجرای اسکریپت به این صورت خواهد بود:

root@kali:/opt# simplels.sh  
simpleadd.sh  
simplels.sh

 Script Parameters

گاهی اوقات، شما نیاز دارید که پارامترهایی را به اسکریپت Bash خود بدهید. برای این کار، باید هر پارامتر را با فاصله از هم جدا کنید و سپس می‌توانید این پارامترها را داخل اسکریپت Bash دستکاری کنید. بیایید یک ماشین حساب ساده (simpleadd.sh) بسازیم که دو عدد را با هم جمع کند:

#!/bin/bash  
#ماشین حساب ساده که دو عدد را جمع می‌کند  
#ذخیره اولین پارامتر در متغیر num1  
NUM1=$1  
#ذخیره دومین پارامتر در متغیر num2  
NUM2=$2  
#ذخیره نتایج جمع در متغیر total  
TOTAL=$(($NUM1 + $NUM2))  
echo '########################'  
printf "%s %d\n" "The total is =" $TOTAL  
echo '########################'  

در اسکریپت قبلی می‌بینید که ما به پارامتر اول با استفاده از دستور $1 و پارامتر دوم با استفاده از $2 دسترسی پیدا کردیم (شما می‌توانید هر تعداد پارامتر که می‌خواهید اضافه کنید). حالا بیایید دو عدد را با استفاده از اسکریپت جدید خود جمع کنیم (توجه کنید که من از این پس اسکریپت‌هایم را در پوشه /opt ذخیره می‌کنم):

root@kali:/opt# simpleadd.sh 5 2  
########################  
The total is = 7  
########################  

یک محدودیت در اسکریپت قبلی وجود دارد؛ این اسکریپت فقط می‌تواند دو عدد را جمع کند. اگر بخواهید انعطاف‌پذیری بیشتری داشته باشید و بتوانید از دو تا پنج عدد جمع کنید، در این صورت می‌توانیم از قابلیت پارامتر پیش‌فرض استفاده کنیم. به عبارت دیگر، به طور پیش‌فرض تمام مقادیر پارامترها به صفر تنظیم می‌شوند و پس از وارد کردن مقدار واقعی از سوی کاربر، جمع می‌شوند:

#!/bin/bash  
#ماشین حساب ساده که تا پنج عدد را جمع می‌کند  
#ذخیره اولین پارامتر در متغیر num1  
NUM1=${1:-0}  
#ذخیره دومین پارامتر در متغیر num2  
NUM2=${2:-0}  
#ذخیره سومین پارامتر در متغیر num3  
NUM3=${3:-0}  
#ذخیره چهارمین پارامتر در متغیر num4  
NUM4=${4:-0}  
#ذخیره پنجمین پارامتر در متغیر num5  
NUM5=${5:-0}  
#ذخیره نتایج جمع در متغیر total  
TOTAL=$(($NUM1 + $NUM2 + $NUM3 + $NUM4 + $NUM5))  
echo '########################'  
printf "%s %d\n" "The total is =" $TOTAL  
echo '########################'  

برای درک نحوه کارکرد این اسکریپت، بیایید به متغیر NUM1 به عنوان مثال نگاه کنیم (همین مفهوم برای پنج متغیر دیگر هم اعمال می‌شود). ما به آن دستور می‌دهیم که اولین پارامتر را از ترمینال بخواند و اگر توسط کاربر وارد نشده بود، آن را به صفر تنظیم کند، همانطور که در :-0 آمده است.
با استفاده از متغیرهای پیش‌فرض، ما دیگر محدود به جمع پنج عدد نیستیم؛ از این پس می‌توانیم هر تعداد عدد که می‌خواهیم جمع کنیم، اما حداکثر تعداد آن پنج عدد خواهد بود (در مثال زیر، سه عدد را جمع می‌کنیم):

root@kali:~# simpleadd.sh 2 4 4  
########################  
The total is = 10  
########################  

نکته

اگر می‌خواهید تعداد پارامترهای وارد شده در اسکریپت را بدانید، می‌توانید از $# برای به دست آوردن تعداد کل استفاده کنید. بر اساس مثال قبلی، مقدار $# برابر با سه خواهد بود زیرا سه آرگومان به اسکریپت ارسال کرده‌ایم. اگر خط زیر را بعد از خط printf اضافه کنید:

printf "%s %d\n" "The total number of params =" $#  

باید در پنجره ترمینال چیزی مشابه زیر مشاهده کنید:

root@kali:~# simpleadd.sh 2 4 4  
########################  
The total is = 10  
The total number of params = 3  
########################  

User Input

یکی دیگر از روش‌ها برای تعامل با ورودی‌های ارائه شده از طریق اسکریپت شل استفاده از تابع read است. بهترین راه برای توضیح این، استفاده از مثال‌ها است. از کاربر خواهیم خواست تا نام و نام خانوادگی خود را وارد کند و سپس نام کامل او را در صفحه نمایش چاپ می‌کنیم:

#!/bin/bash  
read -p "Please enter your first name:" FIRSTNAME  
read -p "Please enter your last name:" LASTNAME  
printf "Your full name is: $FIRSTNAME $LASTNAME\n"  

برای اجرای آن، فقط نام اسکریپت را وارد می‌کنیم (دیگر نیازی به ارسال پارامترها مانند قبل نداریم). به محض وارد کردن نام اسکریپت، پیام‌هایی که در اسکریپت قبلی تعریف کرده‌ایم برای ما ظاهر می‌شود:

root@kali:~# nameprint.sh  
Please enter your first name:Gus  
Please enter your last name:Khawaja  
Your full name is: Gus Khawaja  

 Functions

توابع روشی هستند برای سازماندهی اسکریپت Bash شما در بخش‌های منطقی به جای داشتن یک ساختار بی‌نظم (که برنامه‌نویسان به آن spaghetti code می‌گویند). بیایید برنامه ماشین حساب قبلی را دوباره سازماندهی کنیم (بازنویسی کنیم) تا بهتر به نظر برسد.

این اسکریپت Bash (در شکل 2.3) به سه بخش تقسیم می‌شود:

■ در بخش اول، تمام متغیرهای سراسری (global variables) ایجاد می‌شوند. متغیرهای سراسری در داخل هر تابعی که ایجاد کنید قابل دسترسی هستند. برای مثال، ما می‌توانیم از تمام متغیرهای NUM که در مثال اعلام شده‌اند داخل تابع add استفاده کنیم.
■ سپس، توابع را می‌سازیم و برنامه‌های خود را به بخش‌های منطقی تقسیم می‌کنیم. تابع print_custom() تنها متنی را چاپ می‌کند که به آن می‌دهیم. ما از $1 برای دسترسی به مقدار پارامتر که به این تابع ارسال شده (که رشته CALCULATOR است) استفاده می‌کنیم.
■ در نهایت، هر تابع را به صورت متوالی فراخوانی می‌کنیم (هرکدام را با نامشان). ابتدا هدر را چاپ می‌کنیم، سپس اعداد را جمع می‌کنیم و در نهایت نتایج را چاپ می‌کنیم.

Conditions and Loops

حالا که اصول اولیه اسکریپت‌نویسی Bash را یاد گرفته‌اید، می‌توانیم تکنیک‌های پیشرفته‌تری را معرفی کنیم. زمانی که در اکثر زبان‌های برنامه‌نویسی (مانند PHP، Python، C، C++، C# و غیره) و همچنین اسکریپت‌نویسی Bash برنامه می‌نویسید، با شرایط (دستورات if) و حلقه‌ها مواجه خواهید شد، همانطور که در شکل 2.4 نشان داده شده است.

 Conditions شرایط

یک دستور if به الگوی زیر عمل می‌کند:

if [[ مقایسه ]]  
then  
 True, do something 
else  
 False, Do something else 
fi

اگر توجه کرده‌اید، بهترین راه برای توضیح این الگو از طریق مثال‌ها است. بیایید یک برنامه بسازیم که با استفاده از Nmap به یک هاست پینگ بزند و وضعیت ماشین را بسته به شرط نمایش دهد (هاست بالا یا پایین است):

#!/bin/bash  
#پینگ کردن یک هاست با استفاده از Nmap  
### متغیرهای سراسری ###  
#ذخیره آدرس IP  
IP_ADDRESS=$1  

function ping_host(){  
  ping_cmd=$(nmap -sn $IP_ADDRESS | grep 'Host is up' | cut -d '(' -f 1)  
}  

function print_status(){  
  if [[ -z $ping_cmd ]]  
  then  
    echo 'Host is down'  
  else  
    echo 'Host is up'  
  fi  
}  

ping_host  
print_status

دستور nmap یا یک رشته خالی باز می‌گرداند اگر هاست پایین باشد یا مقدار “Host is up” را بر می‌گرداند اگر پاسخ دهد. (سعی کنید دستور کامل nmap را در پنجره ترمینال خود اجرا کنید تا تفاوت‌ها را ببینید. اگر این کار را انجام می‌دهید، $IP_ADDRESS را با یک آدرس IP واقعی جایگزین کنید.) در شرط if، گزینه -z بررسی می‌کند که آیا رشته خالی است؛ اگر بله، سپس “Host is down” چاپ می‌شود و در غیر این صورت “Host is up” چاپ می‌شود:

root@kali:~# simpleping.sh 10.0.0.11  
Host is down  
root@kali:~# simpleping.sh 10.0.0.1  
Host is up

سایر دستورات شرطی

اما در مورد سایر دستورات شرطی چه می‌شود؟ در واقع شما می‌توانید مقادیر عددی، متنی یا فایل‌ها را مقایسه کنید، همانطور که در جدول‌های 2.1، 2.2 و 2.3 نشان داده شده است.

 Loops

شما می‌توانید حلقه‌ها را به دو روش مختلف بنویسید: استفاده از حلقه while یا استفاده از حلقه for. بیشتر زبان‌های برنامه‌نویسی از همان الگوی حلقه‌ها استفاده می‌کنند. بنابراین، اگر متوجه شوید که حلقه‌ها در Bash چگونه کار می‌کنند، همان مفهوم در زبان‌هایی مانند Python نیز قابل استفاده خواهد بود. حلقه while به ساختار زیر عمل می‌کند:

while [[ شرط ]]
do
   do something 
done

بهترین راه برای توضیح یک حلقه از طریق یک شمارنده از 1 تا 10 است. ما برنامه‌ای خواهیم ساخت که یک نوار پیشرفت را نمایش دهد:

#!/bin/bash
#نوار پیشرفت با حلقه while
#شمارنده
COUNTER=1
#نوار
BAR='##########'
while [[ $COUNTER -lt 11 ]]
do
  #چاپ پیشرفت نوار از ایندکس صفر
  echo -ne "\r${BAR:0:COUNTER}"
  #خوابیدن به مدت 1 ثانیه
  sleep 1
  #افزایش شمارنده
  COUNTER=$(( $COUNTER +1 ))
done

توجه کنید که شرط ([[ $COUNTER -lt 11 ]]) در حلقه while همان قوانین شرط if را دنبال می‌کند. از آنجایی که می‌خواهیم شمارنده در عدد 10 متوقف شود، از فرمول ریاضی زیر استفاده خواهیم کرد: counter<11. هر بار که شمارنده افزایش می‌یابد، پیشرفت نوار نمایش داده می‌شود. برای جذاب‌تر کردن این برنامه، آن را به مدت یک ثانیه متوقف می‌کنیم قبل از اینکه وارد شماره بعدی شویم.

از سوی دیگر، حلقه for به الگوی زیر عمل می‌کند:

for ... in [لیست موارد]
do
   something 
done

ما از همان مثال قبلی استفاده خواهیم کرد، اما این بار از حلقه for استفاده می‌کنیم. شما متوجه خواهید شد که حلقه for انعطاف‌پذیرتر از حلقه while است. (راستش، من به ندرت از حلقه while استفاده می‌کنم.) همچنین، نیازی به افزایش شمارنده ایندکس ندارید؛ این کار به طور خودکار برای شما انجام می‌شود:

#!/bin/bash
#نوار پیشرفت با حلقه For
#نوار
BAR='##########'
for COUNTER in {1..10}
do
  #چاپ پیشرفت نوار از ایندکس صفر
  echo -ne "\r${BAR:0:$COUNTER}"
  #خوابیدن به مدت 1 ثانیه
  sleep 1
done

 File Iteration تکرار فایل‌ها

برای خواندن یک فایل متنی در Bash با استفاده از حلقه for، شما می‌توانید اینطور عمل کنید:

for line in $(cat filename)
do
 do something 
done

در مثال زیر، ما لیستی از آدرس‌های IP را در یک فایل به نام ips.txt ذخیره خواهیم کرد. سپس از برنامه پینگ Nmap که قبلاً ساختیم استفاده می‌کنیم تا بررسی کنیم که آیا هر آدرس IP بالا است یا پایین. علاوه بر این، نام DNS هر آدرس IP را نیز بررسی خواهیم کرد:

#!/bin/bash
#پینگ کردن و دریافت نام DNS از لیستی از آدرس‌های IP ذخیره شده در یک فایل
#از کاربر خواسته می‌شود که نام فایل و مسیر آن را وارد کند.
read -p "Enter the IP addresses file name / path:" FILE_PATH_NAME

function check_host(){
  #اگر مقدار آدرس IP خالی نباشد
  if [[ -n $IP_ADDRESS ]]
  then
    ping_cmd=$(nmap -sn $IP_ADDRESS | grep 'Host is up' | cut -d '(' -f 1)
    echo '------------------------------------------------'
    if [[ -z $ping_cmd ]]
    then
      printf "$IP_ADDRESS is down\n"
    else
      printf "$IP_ADDRESS is up\n"
      dns_name
    fi
  fi
}

function dns_name(){
  dns_name=$(host $IP_ADDRESS)
  printf "$dns_name\n"
}

#تکرار در آدرس‌های IP داخل فایل
for ip in $(cat $FILE_PATH_NAME)
do
  IP_ADDRESS=$ip
  check_host
done

اگر با دقت این فصل را دنبال کرده باشید، باید قادر به درک تمام موارد موجود در کد قبلی باشید. تفاوت اصلی در این برنامه این است که من از فاصله‌گذاری تب استفاده کرده‌ام تا اسکریپت تمیزتر به نظر برسد. مثال قبلی بیشتر آنچه که تاکنون انجام داده‌ایم را پوشش می‌دهد، از جمله موارد زیر:

  • ورودی کاربر
  • اعلام متغیرها
  • استفاده از توابع
  • استفاده از شرایط if
  • تکرار حلقه‌ها
  • چاپ به صفحه نمایش

خلاصه

امیدوارم که تمام تمرین‌ها را در این فصل انجام داده باشید، به‌ویژه اگر شما تازه‌کار در برنامه‌نویسی هستید. بسیاری از مفاهیم ذکر شده برای زبان‌های برنامه‌نویسی مختلف قابل استفاده هستند، بنابراین تمرین‌ها را فرصتی برای یادگیری اصول در نظر بگیرید. من شخصاً از اسکریپت‌نویسی Bash برای سناریوهای کوچک و سریع استفاده می‌کنم. اگر بخواهید برنامه‌های پیچیده‌تری بسازید، می‌توانید این کار را با استفاده از Python انجام دهید. نگران نباشید! در ان دوره های آموزشی درباره Python خواهید آموخت تا بتوانید هر موقعیتی را که می‌خواهید در حرفه‌تان به عنوان یک تست‌کننده نفوذ حل کنید. در نهایت، این فصل اطلاعات زیادی درباره اسکریپت‌نویسی Bash پوشش داد.

با این حال، اطلاعات بیشتری از آنچه در این فصل آورده شده وجود دارد. در عمل، من از موتورهای جستجوی اینترنتی برای پیدا کردن سریع منابع اسکریپت‌نویسی Bash استفاده می‌کنم. در واقع، نیازی به حفظ کردن همه چیزهایی که در این مقاله آموختید نیست.

دیدگاه 1
  1. H@nif says

    سلام و درود
    وقت بخیر
    خدا قوت
    ضمن تشکر از زحمات شما، پیشنهاد میگردد، مطالب و مقالات اینچنینی با توجه به زحمت کشیده شده توسط تهیه کننده بصورت فایل هم قابل دانلود بوده تا بصورت منسجم و قابل آرشیو، مطالب ارزشمند سایت مورد استفاده کاربر قرار گیرد.
    با تشکر

دیدگاه

آدرس ایمیل شما منتشر نخواهد شد.