آموزش‌های خط فرمانی

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

آموزش‌های خط فرمانی

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

تغذیه داده‌های محدود به اسکریپت


سند اینجا(here document) خصیصه‌ای از ترکیب دستوری(syntactic) پوسته بورن است، که تغذیه داده‌ها به برنامه را بدون ذخیره آنها در یک فایل خارجی میسر می‌سازد. این ویژگی به همان خوبی در پوسته‌های POSIX، Korn و Bash نیز کار می‌کند.

قالب اصلی عبارت است از:

someprogram <<WORD
داده‌های شما
go
here
WORD

در اینجا، someprogram می‌تواند هر برنامه‌ای باشد که از ورودی استاندارد می‌خواند (رایج‌ترین آنها cat است)، و WORD می‌تواند هر کلمه متمایز کننده‌ای که مایل هستید، باشد. (EOF یک انتخاب رایج است.)

سند اینجا(Here document)ها با این قالب خصوصیات ویژه‌ای دارند:

  • جایگزینی‌های پوسته( از قبیل ‎ $variable‎) در سند اینجا انجام می‌شوند.

  • دومین کلمه متمایز کننده خودش باید در یک سطر جداگانه و در ستون اول قرار داشته باشد.
  • هر فضای سفید داخل سند اینجا، حفظ می‌گردد، از جمله فضای سفید جداکننده سطر.

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

someprogram <<'WORD'
داده‌های شما
$go
`here`
WORD

اگر می‌خواهیم قادر به ایجاد تورفتگی در سنداینجا باشیم، می‌توانیم کاراکتر - (خط تیره) را پیشوند کلمه متمایزکننده نماییم:

if ...
    while ....
        someprogram <<-WORD
        this is
        an indented
        here document
        WORD
    done
fi

در این شکل تمام کاراکترهای tab پیشتاز (فاصله‌ها خیر!) حذف خواهند شد. هیچگونه مقرراتی برای حذف فاصله‌های پیشتاز سطر یا فاصله‌ها و tabهای همراه هم از ابتدای سطر وجود ندارد. (محدودیت‌های قواعد دستوری Makefileها را به خاطر بیاورید، مجاب خواهید شد.)

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

Here Strings

در bash، گونه‌ای از سنداینجا به نام رشته‌اینجا(here string) وجود دارد. این جمع و جور تر است، اما محدودتر نیز می‌باشد:

read -a octets <<< "$ipaddr"

عملگر ‎<<<‎ نقشی مشابه نقش ‎ <<‎ در سنداینجا دارد، اما کلمه نگهبان برای اینکه به ما بگوید، کجا ورودی تمام می‌شود، وجود ندارد. در عوض، عملگر ‎ <<<‎ با یک کلمه منفرد دنبال می‌شود(نقل‌قول ها دوست شما هستند!). کلمه به اضافه سطر جدید، ورودی استاندارد فرمان می‌شود.


  • سنداینجا (آخرین ویرایش ‎2013-06-10 19:59:13‎ توسط GreyCat)

NamedPipes


کار با لوله‌های با نام

لوله‌ها امکان ارتباط پردازشها با یکدیگر را فراهم می‌کنند. همچنین لوله ممکن است به عنوان FIFO (اختصاری برای First In- First Out) شناخته شود.

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

مثال زیر نمونه‌ای از لوله نام‌گذاری شده است، در اینجا به عنوان pipe1 نامیده شده.

 cd /tmp
 mkfifo pipe1

برای ارسال یک پیغام به لوله، از این استفاده کنید:

 echo "hello" > pipe1

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

امکان دارد در ترمینال دیگری، اطلاعات از لوله جمع آوری گردد، به این شکل:

 cat /tmp/pipe1

اکنون توسط cat اطلاعات از لوله خوانده خواهد شد( و در ترمینال نوشته می‌شود)، و پردازش نویسندهِ مسدودشده برای ادامه یافتن آزاد می‌شود.

برای برخی اطلاعات بیشتر، پرسش و پاسخ شماره ۸۵ را ببینید.

مثال همگامی دوطرفه سرویس‌دهنده- سرویس‌گیرنده

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

ادامه مطلب

پیش‌گیری از رونویسی ناخواسته فایل


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

چگونه کار می‌کند

ls > list

تنظیم noclobber را امتحان کنید

set -o noclobber

دوباره انجام بدهید

ls > list
bash: list: cannot overwrite existing file 

در صورتیکه noclobber برقرار باشد چگونه فایل را رونویسی نماییم

اگر تصمیم به رونویسی فایل گرفته‌اید، می‌توانید روش ‎>|‎ را به کار ببرید. از این قرار:

ls >| list 

غیر فعال نمودن noclobber

درست مانند برقرار کردن noclobber، غیرفعال کردن آن نیز میسر است، چنان که با کاربرد عملگر تغییر مسیر ‎>‎ رونویسی بتواند انجام گردد.

set +o noclobber


NoClobber (آخرین ویرایش ‎2012-09-27 12:53:11‎ توسط Valentin Bajrami)


اصلاحیه‌ای برای بسط glob


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

به طور عادی، وقتی یک glob که بر هیچ نام فایلی منطبق نمی‌شود، بسط داده می‌شود، بدون تغییر باقی می‌ماند. بدین معنی که نتایجی مانند این به دست می‌آورید:

  •  $ rm *.bak
     rm: cannot remove `*.bak': No such file or directory

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

به هرحال، این موضوع در برنامه‌نویسی باعث برخی نتایج نامطلوب می‌گردد. یک آرایه مانند این را ملاحظه کنید:

  •  # Bash  در پوسته
     files=(*)
     echo "There are ${#files[*]} files here."

اگر هیچ فایلی با glob انطباق نیابد، این ناموفق است درحالیکه یک فایل گزارش خواهد نمود، به علت آنکه آرایه با یک عنصر منفرد * بارگیری می‌شود.

گزینه nullglob امکان اجتناب از این مشکل را برای ما فراهم می‌کند. اگر این گزینه تنظیم شود، جانشینِ منطبق نشده به جای اینکه به عنوان یک کلمه منفرد آنجا بماند، کاملاً کنار گذاشته می‌شود. -- با صفر کلمه جایگزین می‌شود-- .

  •  # Bash  در پوسته
     shopt -s nullglob
     files=(*)
     echo "There are ${#files[*]} files here."

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

  •   shopt -s nullglob
     ls *.xyzqj
     # .در این حالت تمام فایلهای این دایرکتوری لیست خواهند شد
     # ‎.بدون شناسه به کار برود ls‎ درست مانند موقعی که دستور  

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

  •  # Bash در پوسته
     shopt -s dotglob
     shopt -s nullglob
     files=(*)
     echo "There are ${#files[*]} files here."

فقط به خاطر داشته باشید که این گزینه‌ها تا موقعی که غیر فعال نشده‌اند، برای پردازش پوسته جاری مؤثر باقی می‌مانند.

ادامه مطلب

توصیف‌گرهای فایل


توصیف‌گرهای فایل

یک توصیف‌گر فایل‎(FD)‎ یک عدد است که به یک فایل باز اشاره می‌کند. هر پردازش مجموعه توصیف‌گرهای فایل اختصاصی خود را دارد، اما FDها از پردازش پدر به پردازشهای فرزند به ارث می‌رسند.

هر پردازشی سه FD را از پدرش به ارث خواهد برد: 0 (ورودی استاندارد)، باز برای خواندن، و 1 (خروجی استاندارد)، و 2 (خطای استاندارد) باز برای نوشتن. پردازشی که بدون یکی از اینها یا بیشر، شروع بشود ممکن است به طور غیر قابل پیش‌بینی رفتار کند. (بنابراین هرگز stderr را نبندید. به جای آن همیشه به ‎/dev/null‎ هدایت نمایید.)

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

پوسته‌ها برای کار با توصیف‌گرهای‌فایل از تغییر مسیر استفاده می‌کنند. برای FDهای از قبل موجود، با استفاده از ترکیب دوتایی کردن توصیف‌گرفایل، خروجی می‌تواند، به آنها ارسال گردد, یا ورودی می‌تواند از آنها خوانده شود:

echo "unexpected error: $foo" 1>&2

while read -r line 0<&3; do ...

ادامه مطلب