پرسش و پاسخ شماره ۳۳ - آموزش اسکریپت نویسی
X
تبلیغات
رایتل

آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

#!/bin/bash

پرسش و پاسخ شماره ۳۳

پرسش و پاسخ شماره ۳۳

چگونه می‌توانم شماره شناسایی پردازشی را با دادن نام آن پردازش به دست آورم؟

به طور معمول به پردازش با استفاده از شماره شناسایی پردازش(PID) رجوع می‌شود، و فرمان‎ ps(1)‎ می‌تواند اطلاعات هر پردازشی با شماره شناسایی (ID) داده شده را نمایش بدهد، به عنوان مثال

    $ echo $$         # شماره شناسایی پردازش من
    21796
    $ ps -p 21796
      PID TTY          TIME CMD
    21796 pts/5    00:00:00 ksh

اما خیلی اوقات شماره شناسایی یک پردازش معلوم نیست، بلکه فقط نام آن مشخص می‌باشد. بعضی سیستم عامل‌ها، به عنوان مثال سولاریس، BSD، و برخی نگارشهای لینوکس، دارای یک دستور اختصاصی برای جستجوی پردازشی با نام معلوم می‌باشند، که ‎ pgrep(1)‎ نامیده شده است:

    $ pgrep init
    1

حتی اغلب یک برنامه تخصصی‌تر نه تنها برای یافتن ID پردازش یک فرآیند با نام معین، بلکه همچنین برای ارسال سیگنال به آن پردازش، در دسترس می‌باشد:

    $ pkill myprocess

بعضی سیستم‌ها ‎ pidof(1)‎ را نیز فراهم نموده‌اند. این با pgrep در آن،شماره شناسایی‌های پردازش چندتاییِ خروجی، فقط با فاصله از هم جدامی‌شوند نه با سطر جدید، تفاوت دارد زیرنویس مترجم 1 .

    $ pidof cron
    5392

اگر این برنامه‌ها در دسترس نیستند، کاربر می‌تواند خروجی فرمان ps را با استفاده از grep جستجو نماید.

مشکل عمده موقع استفاده از grep با خروجی فرمان ps آنست که grep ممکن است با مدخل ps خودش منطبق شود(این مورد را امتحان کنید: ‎ps aux | grep init‎). برای وخیم‌تر شدن موضوع، این در هر نوبت اجرا اتفاق نمی‌افتد، نام فنی این مورد RaceCondition است. برای اجتناب از آن چند روش موجود است:

  • استفاده از ‎ grep -v ‎   در انتها
         ps aux | grep name | grep -v grep
    تمام سطرهای شامل "grep" را از خروجی پاک می‌کند. اشکال: همیشه وضعیت خروج ‎ grep -v‎ را خواهید داشت، بنابراین به عنوان مثال نمی‌توانید وجود یک پردازش خاص را بررسی کنید.
  • استفاده از ‎ grep -v‎ در وسط
         ps aux | grep -v grep | grep name
    این دقیقاً همان کار را انجام می‌دهد، به استثنای آنکه وضعیت خروج "grep name" قابل دستیابی است و نشان دهنده «name پردازشی از ps هست» یا «name پردازشی از ps نیست» می‌باشد. هنوز اشکال شروع یک پردازش جدید‎(grep -v)‎ را دارد.
  • استفاده از ‎ []‎ در grep
         ps aux | grep [n]ame

    این مورد فقط پردازش grep مورد نیاز را تولید می‌کند. رمز آن در کاربرد کلاس کاراکتر ‎ []‎ است(عبارتهای منظم). قرار دادن تنها یک کاراکتر در گروه کاراکتری معمولاً به هیچ وجه معقول نیست، زیرا ‎ [c]‎ همیشه با یک "c" تطبیق می‌کند. در این حالت، نیز همانطور است. ‎grep [n]ame‎ کلمه "name" را جستجو می‌کند. اما چون پردازش متعلق به خود grep مدخلی را لیست می‌کند که شما اجرا نموده‌اید(‎"grep [n]ame"‎) و "grep name" نیست، با خودش منطبق نمی‌شود.

لفاظی greycat: مدیریت 2daemon

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

اکثر اوقات موقعی که شخصی چنین سؤالی می‌پرسد، به دلیل آنست که می‌خواهد با تکنیک‌های ابتدایی اسکریپت‌نویسی یک daemon را مدیریت نماید. انواع همگانی این پرسشها عبارتند از: « چگونه می‌توانم PID فلان پردازش خود را به دست آورم....به طوری که اگر آن پردازش از قبل در حال اجرا نباشد آن را شروع کنم» یا «چطور می‌توانم PID بَهمان پردازش خود را به دست آورم... چون می‌خواهم در صورتیکه از قبل فعال شده است از اجرای آن توسط اسکریپت اجتناب نمایم.» این پرسشها هر دو به طور خطرناکی منجر به ایجاد ضعف سیستم می‌گردند.

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

while true; do
   mydaemon --in-the-foreground
done

که در آن ‎ --in-the-foreground‎ گزینه‌ای است که اگر وجود داشته باشد، باید به daemon داده شود تا از بردن خودش به طور خودکار به پس زمینه اجتناب نماید. (اغلب، ‎ -d‎ این کار را انجام می‌دهد و سودمندی بیشتری از اجرای daemon با تفصیل‌نویسی افزایش یافته را دارد.) برنامه‌هایی کهdaemonها را در خود دارند ممکن است آماج بعدی لفاظی greycat باشند یا نباشند....

اگر این خیلی ساده‌لوحانه است، به daemontools یا runit که برنامه‌هایی برای مدیریت سرویسها می‌باشند، نگاه کنید.

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

مدیریت پردازش، مباحثی مانند«من می‌خواهم گروه job خود را به 5 رشته تقسیم نموده و تمام آنها را به طور موازی اجرا نمایم.» را هم پوشش می‌دهد. لطفاً آن را بخوانید.


  1. مترجم: یک مثال مناسب برای مشاهده تفاوت خروجی دو دستور pgrep و pidof

       $pidof getty
       1836 1083 1034 1025 1006 999
    
       $pgrep getty
       999
       1006
       1025
       1034
       1083
       1836
    
    (1)
  2. مترجم: برنامه‌های کمکی که معمولاً به طور صریح فراخوانی نمی‌شوند، اما به حالت خاموش برای وقوع شرط یا شرایطی در انتظار می‌مانند، مانند سرویس چاپ که تا رسیدن یک درخواست چاپ در انتظار می‌ماند. (2)

CategoryShell

پرسش و پاسخ 33 (آخرین ویرایش ‎ 2009-12-30 18:39:04 ‎ توسط MatthiasPopp)