یک اسکریپت wrapper یکی از معمولترین موارد استفاده برای اسکریپت پوسته است. کار یک wrapper به جای تلاش برای دوباره پیادهسازی قابلیت یک ابزار موجود، انتقال دادن ورودیهایش همراه با تغییر و تبدیل اندک به برخی ابزارهای دیگر است. این مورد، مقدار قابل توجهی از زحمت و دردسر را کاهش میدهد.
اصلیترین شکل یک اسکریپت wrapper این است:
#!/bin/sh exec /some/weird/place/toolname ${1+"$@"}
به طور کلی، موقع نوشتن یک wrapper، ما قابلحملترین ترکیب دستوری ممکن را به کار میبریم. اگر تمام آنچه میخواهیم انجام بدهیم، انتقال دادن ورودیها به برخی برنامههای دیگر است، معمولاً به کد تجملی، مختص-پوسته یا مختص-پلاتفرم نیازی نیست. در حقیقت، شاید کد فوق میتوانست با یک پیوند نمادین جایگزین شده باشد. یک اسکریپت wrapper کمی واقعگرایانهتر، میتواند مانند این به نظر آید:
#!/bin/sh CDR_SECURITY=8:dvd,clone,.... export CDR_SECURITY exec cdrecord-prodvd ${1+"$@"}
این wrapper یک متغیر محیط را تنظیم میکند، و سپس یک برنامه دیگر را با همان شناسهها و ورودی که اسکریپت wrapper دریافت کرده، فراخوانی میکند.
شبانگ #!/bin/sh به علت این به کار میرود که ما به هر چیزی که در پوسته بورن معمولی حضور ندارد، نیاز نداریم. ما در حال به کار بردن قابلحملترین ترکیب دستوری هستیم، بنابراین wrapper در هر سیستم یونیکس احتمالی که پیدا کنیم میتواند اجرا گردد. export بدین گونه در یک سطر جداگانه است، بعد از اینکه متغیر export شونده به مقدارش تنظیم شده باشد.
فرمان exec سبب میگردد ابزاری که ما بستهبندی میکنیم دارای همان PID خودمان بشود. این مطلب در صورتیکه پردازش در حال مدیریت شدن توسط چیزی است که میخواهد یک رابطه پدر-فرزندی با آن را به منظور ارسال سیگنالها، یا واقعاً برای ثبت کردن PID پردازش نگهداری کند، با اهمیت است. همچنین، لازم نیست یک نمونه از پوسته به صورت بلااستفاده در حافظه واگذار شود، exec یک پردازش انشعاب صرفهجویی میکند، و از این جهت کاملاً ثمربخش است.
به خاطر بیاورید که فقط پارامترهای non-scalar (پارامترهایی که وقتی نقلقول دوگانه شدهاند میتوانند به چندین کلمه بسط داده شوند - *, @, array[@] و array[*]) وقتی unset باشند به هیچ کلمهای بسط نمییابد. بنابراین "${1+"$@"}", "$1", "${a[0]}", و نظایر آن، هر یک در صورتیکه نقلقول دوگانه شده باشند حداقل به یک کلمه بسط خواهند یافت، حتی اگر unset باشند.
شگرد {1+"$@"} به جای "$@" به کار میرود زیرا برخی نگارشهای قدیمی پوسته Bourne یک باگ داشتند، که در آن یک لیست شناسه تهی باعث میگردید "$@" به جای یک لیست شناسه تهی، به یک رشته منفرد با طول صفر (یعنی '') بسط داده شود. ترکیب ${1+...} از طریق نخست کنترل کردن آن که آیا دارای یک لیست شناسه غیرتهی میباشیم بر آن غلبه میکند. اگر داشته باشیم، آنوقت "$@" را برای عبور دادن آن به کار میبریم، در غیر آنصورت، چیزی را عبور نمیدهیم. شما این ساختار را بارها و بارها خواهید دید. (برای مثالهای بیشترِ بسطهای پارامتر تفننی، پرسش و پاسخ شماره ۷۳ را ببینید.)
یک مورد پیچیدهترِ اسکریپت wrapper یک اسکریپت راهانداز daemontools میباشد. سرویسهایی که توسط daemontools مدیریت میشوند برای تنظیم محیط و اجرای پردازشی که مدیریت میشود، به یک برنامه (نوشته شده توسط مدیر سیستم، معمولاً درپوسته Bourne) استناد میکنند. این هم یک مثال (قدری مختصر شده) است:
#!/bin/sh exec /usr/local/bin/softlimit -m 3000000 \ /usr/local/bin/tcpserver -v -x /etc/tcp.smtp.cdb -u 10092 -g 10098 0 smtp \ /usr/local/bin/rblsmtpd -r zen.spamhaus.org \ /var/qmail/bin/qmail-smtpd 2>&1
این مثال جالب توجه است زیرا واقعاً یک مجموعه لایههای پیاز-مانند است. (تمام نرمافزارهای DJB به این روش طراحی میشوند.) اسکریپت راهانداز ما یک اسکریپت پوسته Bourne است که برنامهای به نام softlimit را exec میکند. وظیفه softlimit به سادگی تنظیم کردن محدودیتهای منابع پردازش است ( setrlimit(2) در گنو-لینوکس را ببینید). میتوانستیم یک فرمان ulimit یا limit پوسته را برای همان کار استفاده کنیم، اما به خاطر داشته باشید که ما در حال نوشتن در پوسته بورن میباشیم، که فاقد آن است! از آنرو، DJB برنامه softlimit را به عنوان یک برنامه wrapper (در C) نوشت که محدودیتها را تنظیم میکند و سپس پردازش بعدی در زنجیر را exec مینماید.
( اگر ما به جای پوسته Bourne در حال نوشتن اسکریپت راهانداز خودمان در bash بودیم، آنوقت فراخوانی ulimit کارآمد و پسندیده بود.)
2>&1 در انتهای فرمانِ exec softlimit خطای استاندارد و خروجی استاندارد را با یکدیگر متصل میکند، زیرا یک پردازش دیگر (نمایش نیافته) در حال وقایعنگاری تمام این موارد است.
پردازش بعدی در زنجیر tcpserver از مجموعه ucspi-tcp جناب DJB است. این پردازش محدودیتهایی را که از قبل توسط عنصر قبلیِ زنجیر برقرار گردیده، ارث میبرد. سپس، فایل /etc/tcp.smtp.cdb را میخواند، و گوش دادن به درگاه smtp واسط شبکه 0 (تمام واسط ها) را شروع میکند. موقعی که یک اتصال دریافت میکند، برنامه rblsmtpd را به عنوان UID 10092 و GID 10098 منشعب و اجرا میکند. (همچنین چند متغیر محیط مختلف را تنظیم میکند، اما این یک مقدار فراتر از محدوده این صفحه است.)
برنامه rblsmtpd متغیرهای محیطش را بازرسی میکند (موروثی از جلوتر در زنجیر پردازش)، و بر مبنای آنها، یا جستجوهای DNS منبع اتصال آدرس IP را انجام خواهد داد، یا از روی این مرحله عبور خواهد نمود. اگر جستجوها انجام شود و یک نتیجهِ «فرستنده spam» پیدا شود، یک خطا نوشته میشود، و rblsmtpd خارج میشود. در غیر اینصورت، rblsmtpd پردازش بعدی در زنجیر را exec میکند.
سرانجام، اگر این کار را پیش برده باشیم، qmail-smtpd عملاً یک email از فرستنده دریافت میکند و برای پردازش در صف قرار میدهد.
اسکریپت Wrapper (آخرین ویرایش 2012-03-06 17:42:56 توسط ormaaj)