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

فصل 36- گوناگون

‎36.1‎- پوسته‌های محاوره‌ای و غیر محاوره‌ای و اسکریپت‌ها

پوسته محاوره‌ای فرمان‌ها را از ورودی کاربر در یک tty می‌خواند. از جمله سایر موارد، چنین پوسته‌ای هنگام فعال شدن فایل‌های راه‌اندازی را می‌خواند، یک اعلان نمایش می‌دهد، و به طور پیش‌فرض کنترل ‎job‎ را فعال می‌کند. کاربر می‌تواند با پوسته فعل و انفعال داشته باشد.

یک پوسته در حال اجرای یک اسکریپت همواره پوسته‌ای غیرمحاوره‌ای است. با این وجود، اسکریپت بازهم می‌تواند به tty خود دسترسی داشته باشد. حتی شبیه‌سازی یک پوسته محاوره‌ای در یک اسکریپت نیز امکان‌پذیر است.

#!/bin/bash
MY_PROMPT='$ '
while :
do
  echo -n "$MY_PROMPT"
  read line
  eval "$line"
done
exit 0
# این نمونه اسکریپت و بسیاری از توضیحات بیان شده قبلی را
#  ‎Stéphane Chazelas‎ تهیه نموده (یکبار دیگر تشکر می‌کنم).

بیایید در نظر بگیریم یک اسکریپت محاوره‌ای اسکریپتی باشد که نیازمند ورودی کاربر، معمولاً از طریق دستورات read، است (مثال ‎15-3‎ را ببینید). «حالت واقعی» عملاً یک مقدار شلوغ‌تر از این است. در حال حاضر، فرض کنید یک اسکریپت محاوره‌ای محدود به یک tty است، اسکریپتی است که به وسیله یک کاربر از کنسول یا یک xterm فراخوانی گردیده است.

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

اسکریپت‌های غیرمحاوره‌ای می‌توانند در پس‌زمینه اجرا گردند، اما اسکریپت‌های محاوره‌ای در انتظار برای ورودی که هرگز نمی‌آید بلاتکلیف می‌مانند. این اشکال را با یک اسکریپت expect یا ‎here document‎ تعبیه شده، جهت تغذیه ورودی به یک اسکریپت محاوره‌ای در حال اجرا به صورت یک job پس‌زمینه، مدیریت نمایید. در ساده‌ترین حالت، یک فایل را برای فراهم نمودن ورودی، به دستورالعمل read تغییر مسیر بدهید (‎read variable <file‎). این راه‌حل‌های موقت، تولید اسکریپت‌های چند منظوره‌ای را فراهم می‌نمایند که در حالت‌های محاوره‌ای یا غیرمحاوره‌ای اجرا می‌شوند.

اگر اسکریپتی نیاز داشته باشد بررسی کند که آیا در حال اجرا روی یک پوسته محاوره‌ای است، فقط نیازمند تعیین آن است که آیا متغیر prompt، یعنی ‎$PS1‎ برقرار است. (اگر ورودی از کاربر خواسته می‌شود، آنوقت لازم است اسکریپت اعلانی را نمایش بدهد.)

if [ -z $PS1 ]      # آیا prompt نیست؟
###   # در ‎Bash 4.2+‎ ...
then
  ...               #      غیرمحاوره‌ای
else
  ...               #         محاوره‌ای
fi

به طور جایگزین، اسکریپت می‌تواند وجود گزینه «i» را در نشانوند ‎$-‎ بررسی کند.

case $- in
*i*)               #    پوسته محاوره‌ای
;;
*)                 # پوسته غیرمحاوره‌ای
;;
#    (بر گرفته از ‎"UNIX F.A.Q.," 1993‎)

با این وجود، ‎John Lange‎ یک روش پیشنهادی را با استفاده از ‎-t test operator‎ شرح می‌دهد.

# بررسی جهت یک ترمینال!
fd=0     # stdin

#  همچنانکه به یاد داریم، گزینه ‎-t‎ بازبینی می‌کند که آیا در یک اسکریپت معین
#+      ‎stdin‎‏، ‎[ -t 0 ]‎ یا ‏stdout،‏ ‎[ -t 1 ]‎ در حال اجرا در یک ترمینال است.
if [ -t "$fd" ]
then
  echo interactive
else
  echo non-interactive
fi

#                               اما، به طوری که ‎John‎ توضیح می‌دهد:
# وقتی شما به طور محلی لاگین کرده باشید ‎if [ -t 0 ]‎ کار می‌کند، اما
#  هنگامی که فرمان را از راه دور با ssh فراخوانی کنید ناموفق است.
# بنابراین برای یک بررسی صحیح، باید یک بررسی سوکت نیز انجام دهید.

if [[ -t "$fd" || -p /dev/stdin ]]
then
  echo interactive
else
  echo non-interactive
fi

امکان آن هست که اسکریپت‌ها با گزینه ‎-i‎ یا سرآیند ‎#!/bin/bash -i‎ وادار به اجرا در یک وضعیت محاوره‌ای بشوند. اما آگاه باشید که این کار می‌تواند موجب نمایش پیغام‌های خطا حتی در موقعی که خطا وجود ندارد یا رفتار غیرعادی اسکریپت بشود.