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

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

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

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

جایگزینی پردازش


جایگزینی پردازش

جایگزینی پردازش یک توسعه بسیار سودمند BASH است. مشابه ‎"command" | getline‎ در awk می‌باشد و بخصوص برای کنار گذاشتن پوسته‌های فرعی معلول خط‌لوله‌ها اهمیت دارد.

جایگزینی پردازش در دو شکل ظاهر می‌شود: ‎<(some command)‎ و ‎>(some command)‎. هر کدام نسبت به سیستم عامل، باعث می‌شوند یا یک FIFO در ‎/tmp‎ یا ‎/var/tmp‎ ایجاد بشود، یا یک دستگاه ویژه توصیف‌گر فایل (‎/dev/fd/*‎)، استفاده بشود. ترکیب دستوری جایگزینی توسط نام FIFO یا FD تعویض می‌گردد، وفرمان داخل آن در پس‌زمینه اجرا می‌گردد. جایگزینی در همان مرحله بسط پارامتر و جایگزینی فرمان انجام می‌شود.

یکی از رایج‌ترین موارد استفاده این ویژگی برای پرهیز از ایجاد فایلهای موقتی است، به عنوان مثال، موقع کاربرد ‎diff(1)‎:

ادامه مطلب

پرسش و پاسخ شماره ۱۱۰


آیا می‌توانم چیزی مشابه الگوها(templates) را با bash به کار ببرم؟

Bashهیچ روش درونی برای استفاده از قالب ها( templates) ندارد. اگر چه، نسبت به اهداف واقعی خود، ممکن است فقط بتوانید شگرد ارزیابی فایل با یک bash جدید یا پوسته نمونه را به کار ببرید.

به هر حال، این مطلب در صفحه TemplateFiles بحث شده است.





پرسش و پاسخ 110 (آخرین ویرایش ‎2013-03-18 18:07:40‎ توسط 12)


پرسش و پاسخ شماره ۱۰۹


چگونه می‌توانم بگویم که آیا اسکریپت من منبع شده(به طور نقطه‌ای) یا اجرا گردیده است؟

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

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

کلید در اینجا، و دلیل آنکه من پرسش را به این طریق جمله‌بندی مجدد نموده‌ام، آنست که شما عملاً نمی‌توانید آنچه را کاربر تایپ نموده است تعیین کنید، اما می‌توانید تعیین کنید آیا کُد در حال تفسیر شدن با یک پوسته محاوره‌ای است. این کار را باکنترل یک i در محتوای متغیر ‎$-‎ انجام بدهید:

# POSIX(?)
case $- in
  *i*) : ;; 
    *) echo "You should dot me in" >&2; exit 1;;
esac

یا با استفاده از ترکیب دستوری غیر-POSIX:

# Bash/Ksh
if [[ $- != *i* ]]; then
  echo "You should dot me in" >&2; exit 1
fi

البته، این مورد در حالت‌های ترفندآمیزی مانند «من می‌خواهم فایل من از یک اسکریپت غیرمحاوره‌ای نقطه‌ای بشود...» کار نمی‌کند. برای آن حالت‌ها، پاراگراف اول این صفحه را ببینید.


CategoryShell

پرسش و پاسخ 109 (آخرین ویرایش ‎2012-09-11 07:43:44‎ توسط dslb-088-072-055-065)


انتظار برای خاتمه یافتن پردازش فرزند


چطور در انتظار انجام چند پردازش فرزند بمانم؟

برای انجام این کار روشهای بیشماری موجود است، اما تمام آنها محدود به ابزارهای در دسترس هستند. من به چاره سازی‌های زیر رسیدم .

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

اگر فقط می‌خواهید منتظر برخی، اما نه تمام آنها، بمانید و نگران وضعیت خروج آنها نمی‌باشید، می‌توانید wait را با PIDهای چندگانه فراخوانی کنید:

wait $pid1 $pid2

اگر نیاز دارید، بدانید آیا فرزند موفق یا ناموفق بوده، آنوقت شاید:

waitall() { # PID...
  ## .انتظار برای خروج فرزند و نمایش آنکه آیا همه با وضعیت صفر خارج شده‌اند‎
  local errors=0
  while :; do
    debug "Processes remaining: $*"
    for pid in "$@"; do
      shift
      if kill -0 "$pid" 2>/dev/null; then
        debug "$pid is still alive."
        set -- "$@" "$pid"
      elif wait "$pid"; then
        debug "$pid exited with zero exit status."
      else
        debug "$pid exited with non-zero exit status."
        ((++errors))
      fi
    done
    (("$#" > 0)) || break
    # متوقف گردد؟ sleep وقتی فرزند خاتمه داده می‌شود، چطور این ‎:‎برای انجام ‎
    sleep ${WAITALL_DELAY:-1}
   done
  ((errors == 0))
}

debug() { echo "DEBUG: $*" >&2; }

pids=""
for t in 3 5 4; do
  sleep "$t" &
  pids="$pids $!"
done
waitall $pids

حلقه‌زنی بواسطه ‎kill -0‎ می‌تواند بسیار بی‌کفایت باشد.

اطلاعات مفیدتر می‌تواند در صفحه مدیریت پردازش یافت شود.


CategoryShell

پرسش و پاسخ 108 (آخرین ویرایش ‎2011-09-12 23:03:28‎ توسط GreyCat)


درج نشانه زمان در سطرهای یک جریان داده


چگونه به هر سطر یک جریان مُهرتاریخ بزنم؟

روشهای بیشماری برای انجام این کار هست، اما تمام آنها یا به ابزارهای در دسترس محدود می‌شوند، یا کُند هستند. ما چند نمونه را نشان خواهیم داد.

بیایید اول با روش آهسته قابل حمل شروع کنیم و با این نمونه آن را انجام بدهیم:

# POSIX
while IFS= read -r line; do
  echo "$(date +%Y%m%d-%H:%M:%S) $line"
done

و یکی دیگر که حتی کُندتر است:

awk '{system("printf \"`date +%T ` \">&2")}$0'

و سومی، که به طور جزئی سریعتر است، اما ممکن است بعضی از سطرهای ورودی را خُرد کند:

xargs -I@ -n1 date "+%T @"

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

روشهای متنوعی برای انجام این کار، بدون تولید پردازش فرزند(forking) به ازای هر سطر، وجود دارد، اما تمام آنها نیازمند ابزارهای غیر استاندارد یا پوسته‌های خاص، می‌باشند. ‎Bash 4.2‎ می‌تواند آن را با printf انجام بدهد:

# Bash 4.2
while read -r; do
  printf "%(%Y%m%d-%H:%M:%S)T %s\n" -1 "$REPLY"
done

مشخص کننده قالب ‎%(...)T‎ در bash نگارش ‎4.2‎ جدید است. شناسه ‎-1‎ به او می‌گوید از زمان جاری به جای زمان عبور داده شده به عنوان شناسه، استفاده کند. برای جزئیات، صفحه man مربوط را ملاحظه نمایید.

یک روش دیگر، نوشتن یک perl یک سطری است:

perl -p -e '@l=localtime; printf "%04d%02d%02d-%02d:%02d:%02d ", 1900+$l[5], $l[4], $l[3], $l[2], $l[1], $l[0]'

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

ابزارهای دیگری مخصوصاً برای نشانه‌گذاری زمان فایلهای ثبت وقایع و مشابه، وجود دارد. یکی از آنها multilog از daemontools می‌باشد، اما قالب نشانه‌گذاری زمان آن TAI64N است که قابل خواندن انسانی نیست. دیگری ts از بسته moreutils می‌باشد.


CategoryShell

پرسش و پاسخ 107 (آخرین ویرایش ‎2012-05-19 12:23:00‎ توسط GreyCat)