به راستی، یک اسکریپت میتواند خودش را به طور بازگشتی فراخوانی کند؟
مثال 36-10. اسکریپتی (بیفایده) که به طور بازگشتی خودش را فراخوانی میکند
#!/bin/bash # recurse.sh #آیا یک اسکریپت میتواند به طور بازگشتی خود را احضار کند؟ #بله، اما آیا این دارای هیچ استفاده عملی هست؟ (ادامه را ببینید.) RANGE=10 MAXVAL=9 i=$RANDOM let "i %= $RANGE" #تولید یک عدد تصادفی بین 0 و $RANGE-1 if [ "$i" -lt "$MAXVAL" ] then echo "i = $i" ./$0 #اسکریپت به طور بازگشتی نمونه جدیدی از خود ایجاد میکند. fi #هر اسکریپت فرزند نیز همان کار را انجام میدهد، تا یک $i #+تولید شده، مساوی $MAXVAL بشود. #استفاده از یک حلقه while به جای یک تست if/then باعث مشکلات میگردد. #چرای آن را توضیح بدهید. exit 0 #یادداشت: #------------ #برای آنکه این اسکریپت به درستی کار کند، باید دارای مجوز اجرا باشد. #حتی اگر اسکریپت به وسیله یک فرمان sh فراخوانی گردد، این صدق میکند. #توضیح دهید که چرا چنین است.
مثال 36-11. یک اسکریپت (مفید) که خودش را به طور بازگشتی فراخوانی میکند
#!/bin/bash #دفتر تلفن #نوشته Rick Boivie است، و با مجوز استفاده گردیده است. #تغییراتی به وسیله نگارنده راهنمای ABS اعمال شده است. MINARGS=1 #اسکریپت حداقل یک شناسه لازم دارد. DATAFILE=./phonebook #باید یک فایل داده به نامphonebook #+در دایرکتوری جاری موجود باشد. PROGNAME=$0 E_NOARGS=70 #خطای تعیین نکردن شناسه. if [ $# -lt $MINARGS ]; then echo "Usage: "$PROGNAME" data-to-look-up" exit $E_NOARGS fi if [ $# -eq $MINARGS ]; then grep $1 "$DATAFILE" #اگر $DATAFILE موجود نباشد؟، grep یک پیعام خطا چاپ میکند. else ( shift; "$PROGNAME" $* ) | grep $1 #اسکریپت خودش را به طور بازگشتی فراخوانی میکند. fi exit 0 #اسکریپت در اینجا خارج میشود. #بنابراین، قرار دادن توضیحات و دادهها در پایین #+بدون استفاده از علامت توضیح، مشکل ندارد. #----------------------------------------------------------------------- Sample "phonebook" datafile: John Doe 1555 Main St., Baltimore, MD 21228 (410) 222-3333 Mary Moe 9899 Jones Blvd., Warren, NH 03787 (603) 898-3232 Richard Roe 856 E. 7th St., New York, NY 10009 (212) 333-4567 Sam Roe 956 E. 8th St., New York, NY 10009 (212) 444-5678 Zoe Zenobia 4481 N. Baker St., San Francisco, SF 94338 (415) 501-1631 #------------------------------------------------------------------------ #bash$ pb.sh Roe Richard Roe 856 E. 7th St., New York, NY 10009 (212) 333-4567 Sam Roe 956 E. 8th St., New York, NY 10009 (212) 444-5678 bash$ pb.sh Roe Sam Sam Roe 956 E. 8th St., New York, NY 10009 (212) 444-5678 وقتی بیش از یک شناسه به اسکریپت داده شود، «فقط» سطرهایی #+را چاپ میکند که شامل تمام شناسهها باشند.
مثال 36-12. یک اسکریپت (مفید) دیگر که به طور بازگشتی خودش را فراخوانی میکند
#!/bin/bash #نوشته شده به وسیله Anthony Richardson #با مجوز در راهنمای ABS به کار رفته است. #نحوه کاربرد: usrmnt.sh #توضیحات: mount دستگاه، کاربر فراخوانی کننده باید در #گروه MNTUSERS در فایل /etc/sudoers لیست شده باشد. #-------------------------------------------------------------- #این یک اسکریپت usermount است که با استفاده از sudo دوباره خودش #را اجرا میکند. کاربرِ دارای مجوزهای صحیح، باید به جای تایپ # #فقط تایپ کند: # #من از همین شگرد برای تمام اسکریپتهای sudo خودم #+استفاده میکنم، چون آن را مناسب میدانم. #-------------------------------------------------------------- #اگر متغیر SUDO_COMMAND تنظیم نباشد، در حال اجرا از طریق sudo #+نیستیم، بنابراین دوباره با id واقعی کاربر و گروه اجرا میکنیم. if [ -z "$SUDO_COMMAND" ] then mntusr=$(id -u) grpusr=$(id -g) sudo $0 $* exit 0 fi #فقط در صورتیکه به وسیله sudo اجرا کنیم به اینجا خواهیم رسید. /bin/mount $* -o uid=$mntusr,gid=$grpusr exit 0 #ملاحظات افزوده (از نویسنده این اسکریپت): #------------------------------------------------------------ #(1 لینوکس گزینه «users» را در فایل /etc/fstab مجاز میداند، #طوری که هر کاربر میتواند رسانه جدا شدنی را mount نماید. #اما روی یک سرویسدهنده، من مایل به مجاز کردن تنها چند #دسترسی جداگانه برای رسانه جداشدنی هستم. #دریافتم که کاربرد sudo کنترل بیشتری برای من فراهم میکند. #(2 همچنین دریافتم که sudo نسبت به انجام دادن این وظیفه از #طریق گروهها، بیشتر مناسب است. #(3 این شیوه به هر شخص دارای مجوزهای صحیح، دسترسی root برای #فرمان mount اعطا میکند، بنابراین در مورد کسی که به او #اجازه دسترسی میدهید، دقیق باشید. #شما میتوانید بوسیله استفاده از همین تکنیک در اسکریپتهای #جداگانه mntfloppy، mntcdrom، و mntsamba در باره این که #کدام مدخل بتواند mount شود، کنترل بهتری داشته باشید.
مراحل بازگشت خیلی زیاد، میتواند فضای پشته اسکریپت را تمام کرده، باعث یک segfault بشود. |