خط فرمان لینوکس

ترجمه فارسی LinuxCommand.org

خط فرمان لینوکس

ترجمه فارسی LinuxCommand.org

پارامترهای مکانی

پارامترهای مکانی

وقتی آخرین بار اسکریپت‌مان را ترک کردیم، چیزی مانند این بود:

#!/bin/bash

# sysinfo_page - اطلاعات سیستم HTML اسکریپتی برای تولید یک فایل‎ 

##### ثابت‌ها‎

TITLE="System Information for $HOSTNAME"
RIGHT_NOW=$(date +"%x %r %Z")
TIME_STAMP="Updated on $RIGHT_NOW by $USER"

##### توابع‎

system_info()
{
    echo "<h2>System release info</h2>"
    echo "<p>Function not yet implemented</p>"

}   #  system_info پایان تابع ‎


show_uptime()
{
    echo "<h2>System uptime</h2>"
    echo "<pre>"
    uptime
    echo "</pre>"

}   #  show_uptime پایان تابع ‎


drive_space()
{
    echo "<h2>Filesystem space</h2>"
    echo "<pre>"
    df
    echo "</pre>"

}   #  drive_space پایان تابع ‎


home_space()
{
    # فقط کاربر ارشد می‌تواند این اطلاعات را به دست بیاورد

    if [ "$(id -u)" = "0" ]; then
        echo "<h2>Home directory space by user</h2>"
        echo "<pre>"
        echo "Bytes Directory"
        du -s /home/* | sort -nr
        echo "</pre>"
    fi

}   #  home_space پایان تابع ‎



##### Main

cat <<- _EOF_
  <html>
  <head>
      <title>$TITLE</title>
  </head>
  <body>
      <h1>$TITLE</h1>
      <p>$TIME_STAMP</p>
      $(system_info)
      $(show_uptime)
      $(drive_space)
      $(home_space)
  </body>
  </html>
_EOF_

موارد بسیاری آماده به کار داریم، اما چند ویژگی دیگر نیز هست که من می‌خواهم اضافه کنم:

  1. می‌خواهم نام فایل خروجی در خط فرمان مشخص شود، به علاوه یک نام فایل خروجی پیش‌فرض برای اینکه اگر نامی مشخص نگردد تنظیم کنم.

  2. می‌خواهم یک وضعیت محاوره‌ای ارایه کنم که برای نام فایل استعلام نماید و اگر فایل موجود باشد کاربر را آگاه کرده و برای رونویسی آن نظر کاربر را جویا شود.

  3. به طور طبیعی، می‌خواهم یک گزینه help نیز داشته باشیم که پیغام نحوه کاربرد را نمایش بدهد.

تمام این ویژگی‌ها، با کاربرد گزینه‌های فرمان و شناسه‌ها ارتباط دارند. برای مدیریت گزینه‌های سطر فرمان، ما یک وسیله پوسته به نام پارامترهای مکانی را به کار می‌بریم. پارامترهای مکانی یک گروه از متغیرهای خاص هستند (‎$0‎ تا ‎$9‎) که در بر دارنده محتویات سطر فرمان هستند.

بیایید سطر فرمان زیر را فرض کنیم:

[me@linuxbox me]$ some_program word1 word2 word3

اگر some_program یک اسکریپت پوسته بود، ما می‌توانستیم هر یک از اقلام سطر فرمان را بخوانیم زیرا پارامترهای مکانی محتوی این موارد می‌گردیدند:

  • ‎$0‎ محتوی ‎"some_program"‎
  • ‎$1‎ محتوی ‎"word1"‎
  • ‎$2‎ محتوی ‎"word2"‎
  • ‎$3‎ محتوی ‎"word3"‎

این هم یک اسکریپت که شما می‌توانید این مورد را آزمایش کنید:

#!/bin/bash

echo "Positional Parameters"
echo '$0 = ' $0
echo '$1 = ' $1
echo '$2 = ' $2
echo '$3 = ' $3

یافتن شناسه‌های سطر فرمان

بیشتر اوقات، شما نیاز خواهید داشت وجود شناسه‌ها را برای عمل کردن بر آنها بررسی کنید. چند روش برای انجام این کار وجود دارد. نخست، به سادگی می‌توانید بررسی کنید که آیا ‎$1‎ محتوی چیزی هست، مانند این:

#!/bin/bash

if [ "$1" != "" ]; then
    echo "Positional parameter 1 contains something"
else
    echo "Positional parameter 1 is empty"
fi

دوم، پوسته متغیری به نام ‎$#‎ را نگهداری می‌کند که شامل تعداد اقلام سطر فرمان به غیر از نام فرمان ‎($0)‎ است.

#!/bin/bash

if [ $# -gt 0 ]; then
    echo "Your command line contains $# arguments"
else
    echo "Your command line contains no arguments"
fi

گزینه‌های سطر فرمان

همانطور که قبلاً گفتیم، بسیاری از برنامه‌ها مخصوصاً برنامه‌های پروژه گنو، از هر دو نوع گزینه خط فرمان کوتاه و بلند پشتیبانی می‌کنند. برای مثال، جهت نمایش یک پیغام راهنما برای بسیاری از این برنامه‌ها، شما می‌توانید یا از گزینه ‎"-h"‎ یا گزینه بلندتر ‎"--help"‎ استفاده کنید. نام گزینه‌های بلند به طور معمول با دو خط تیره همراهی می‌گردد. ما در اسکریپت‌های خود این قرارداد را به کار خواهیم برد.

این هم کدی که برای پردازش سطر فرمان‌مان استفاده خواهیم نمود:

interactive=
filename=~/sysinfo_page.html

while [ "$1" != "" ]; do
    case $1 in
        -f | --file )           shift
                                filename=$1
                                ;;
        -i | --interactive )    interactive=1
                                ;;
        -h | --help )           usage
                                exit
                                ;;
        * )                     usage
                                exit 1
    esac
    shift
done

این کد کمی ماهرانه است، بنابراین هنگامی که من تلاش می‌کنم آن را تشریح نمایم بردباری کنید.

دو سطر نخست نسبتاً ساده هستند. ما متغیر interactive را طوری تنظیم کرده‌ایم که تهی باشد. این بیانگر آن است که وضعیت محاوره‌ای در خواست نگردیده است. سپس متغیر filename را برای در بر داشتن نام فایل پیش‌فرض تنظیم کردیم. اگر نام دیگری در سطر فرمان تعیین نشود، این نام فایل به کار خواهد رفت.

پس از اینکه دو متغیر تنظیم شدند، در صورتیکه کاربر هیچ گزینه‌ای به کار نبرد، ما تنظیمات پیش‌فرض را در اختیار داریم.

بعد، یک حلقه while می‌سازیم که در میان تمام اقلام سطر فرمان گردش می‌کنیم و هر یک را با case پردازش می‌کنیم. فرمان case هر گزینه ممکن را یافته و به طور مناسب پردازش خواهد نمود.

اکنون بخش ماهرانه. آن حلقه چگونه کار می‌کند؟ به جادوی shift استناد می‌کند.

shift یک فرمان داخلی است که روی پارامترهای مکانی عمل می‌کند. هر نوبت که شما فرمان shift را احضار می‌کنید، تمام پارامترهای مکانی را یکی به پایین جابه جا می‌کند. ‎$2‎ می‌شود ‎$1‎‏، ‎$3‎ میشود ‎$2‎‏، ‎$4‎ می‌شود ‎$3‎، و به همین ترتیب. این را امتحان کنید:

#!/bin/bash

echo "You start with $# positional parameters"

# حلقه تا موقعی که تمام پارامترها مصرف شده باشند‎
while [ "$1" != "" ]; do
    echo "Parameter 1 equals $1"
    echo "You now have $# positional parameters"

    # جا به جایی تمام پارامترها یکی به طرف پایین‎
    shift

done

گرفتن یک شناسهِ گزینه

گزینه ‎"-f"‎ ما به یک نام فایل معتبر به عنوان یک شناسه احتیاج دارد. ما دوباره shift را برای به دست آوردن مورد بعدی در خط فرمان و تخصیص آن به filename به کار می‌بریم. بعداً باید محتوای filename را برای حصول اطمینان از معتبر بودنش بررسی نماییم.

یکپارچه نمودن پردازش کننده سطر فرمان در اسکریپت

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

#!/bin/bash

# sysinfo_page - اطلاعات سیستم HTML اسکریپتی برای تولید یک فایل‎ 

##### ثابت‌ها‎

TITLE="System Information for $HOSTNAME"
RIGHT_NOW=$(date +"%x %r %Z")
TIME_STAMP="Updated on $RIGHT_NOW by $USER"

##### توابع‎

system_info()
{
    echo "<h2>System release info</h2>"
    echo "<p>Function not yet implemented</p>"

}   #  system_info پایان تابع‎


show_uptime()
{
    echo "<h2>System uptime</h2>"
    echo "<pre>"
    uptime
    echo "</pre>"

}   #  show_uptime پایان تابع‎


drive_space()
{
    echo "<h2>Filesystem space</h2>"
    echo "<pre>"
    df
    echo "</pre>"

}   #  drive_space پایان تابع‎


home_space()
{
    # فقط کاربر ارشد می‌تواند این اطلاعات را به دست بیاورد

    if [ "$(id -u)" = "0" ]; then
        echo "<h2>Home directory space by user</h2>"
        echo "<pre>"
        echo "Bytes Directory"
        du -s /home/* | sort -nr
        echo "</pre>"
    fi

}   #  home_space پایان تابع‎


write_page()
{
    cat <<- _EOF_
    <html>
        <head>
        <title>$TITLE</title>
        </head>
        <body>
        <h1>$TITLE</h1>
        <p>$TIME_STAMP</p>
        $(system_info)
        $(show_uptime)
        $(drive_space)
        $(home_space)
        </body>
    </html>
_EOF_

}

usage()
{
    echo "usage: sysinfo_page [[[-f file ] [-i]] | [-h]]"
}


##### Main

interactive=
filename=~/sysinfo_page.html

while [ "$1" != "" ]; do
    case $1 in
        -f | --file )           shift
                                filename=$1
                                ;;
        -i | --interactive )    interactive=1
                                ;;
        -h | --help )           usage
                                exit
                                ;;
        * )                     usage
                                exit 1
    esac
    shift
done


# کد تست برای بازبینی صحت پردازش سطر فرمان‎

if [ "$interactive" = "1" ]; then
	echo "interactive is on"
else
	echo "interactive is off"
fi
echo "output file = $filename"


# نوشتن اسکریپت (به صورت توضیح نشان‌گذاری شده تا تست کردن کامل شود)‏‎

# write_page > $filename

افزودن وضعیت محاوره‌ای

وضعیت محاوره‌ای با کد پایین پیاده‌سازی می‌گردد:

if [ "$interactive" = "1" ]; then

    response=

    echo -n "Enter name of output file [$filename] > "
    read response
    if [ -n "$response" ]; then
        filename=$response
    fi

    if [ -f $filename ]; then
        echo -n "Output file exists. Overwrite? (y/n) > "
        read response
        if [ "$response" != "y" ]; then
            echo "Exiting program."
            exit 1
        fi
    fi
fi

ابتدا، بررسی می‌کنیم آیا وضعیت محاوره‌ای فعال هست، در غیر اینصورت کاری برای انجام نداریم. بعد، نام فایل را از کاربر سوال می‌کنیم. روشی را که اعلان بیان می‌شود ملاحظه کنید:

echo -n "Enter name of output file [$filename] > "

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

پس از اینکه دارای نام فایل خروجی هستیم، بررسی می‌کنیم که آیا از قبل موجود است. اگر باشد، به کاربر اخطار می‌دهیم. اگر پاسخ کاربر ‎"y"‎ نباشد، منصرف شده و خارج می‌شویم، وگرنه می‌توانیم پیش برویم.