تله
در فصل 10، دیدیم که چگونه برنامه ها می توانند به سیگنال ها پاسخ دهند. ما می توانیم این قابلیت را به اسکریپت های خود نیز اضافه کنیم. در حالی که اسکریپتهایی که تا کنون نوشتهایم به این قابلیت نیاز ندارند (چون زمان اجرای بسیار کوتاهی دارند و فایلهای موقتی ایجاد نمیکنند)، اسکریپتهای بزرگتر و پیچیدهتر ممکن است از داشتن یک روال مدیریت سیگنال بهره ببرند.
هنگامی که ما یک اسکریپت بزرگ و پیچیده طراحی می کنیم، مهم است که در نظر داشته باشیم اگر کاربر هنگام اجرای اسکریپت از سیستم خارج شود یا کامپیوتر را خاموش کند چه اتفاقی می افتد. هنگامی که چنین رویدادی رخ می دهد، یک سیگنال به تمام فرآیندهای تحت تأثیر ارسال می شود. به نوبه خود، برنامه هایی که این فرآیندها را نمایندگی می کنند، می توانند اقداماتی را برای اطمینان از پایان صحیح و منظم برنامه انجام دهند. مثلاً فرض کنید یک اسکریپت نوشتیم که در حین اجرای آن یک فایل موقت ایجاد کرد. در طول طراحی خوب، ما می خواهیم اسکریپت فایل را زمانی که اسکریپت کار خود را تمام می کند حذف کند. همچنین اگر سیگنالی دریافت شد که نشان میدهد برنامه پیش از موعد خاتمه مییابد، هوشمندانه است که اسکریپت فایل را حذف کند.
بر هم زدن مکانیزمی را برای این منظور فراهم می کند که به نام a دام. تله ها با دستور داخلی با نام مناسب پیاده سازی می شوند. دام. دام از نحو زیر استفاده می کند:
دام سیگنال آرگومان [سیگنال...]
جایی که استدلال رشته ای است که خوانده می شود و به عنوان یک دستور و رفتار می شود سیگنال مشخصه سیگنالی است که اجرای فرمان تفسیر شده را آغاز می کند.
در اینجا یک مثال ساده آورده شده است:
#! / bin / bash
# trap-demo: نمایش ساده کنترل سیگنال
#! / bin / bash
# trap-demo: نمایش ساده کنترل سیگنال
تله "echo 'I am ignoring you." SIGINT SIGTERM for i در {1..5}; انجام دادن
echo "تکرار $i از 5" خواب 5
انجام شده
تله "echo 'I am ignoring you." SIGINT SIGTERM for i در {1..5}; انجام دادن
echo "تکرار $i از 5" خواب 5
انجام شده
این اسکریپت تله ای را تعریف می کند که an را اجرا می کند از دست هر بار که سیگنال SIG-INT یا SIGTERM دریافت می شود در حالی که اسکریپت در حال اجرا است، دستور دهید. اجرای برنامه زمانی که کاربر سعی می کند با فشار دادن اسکریپت را متوقف کند به این صورت به نظر می رسد Ctrl-c:
[me@linuxbox ~]$ تله نمایشی
تکرار 1 از 5
تکرار 2 از 5 من شما را نادیده میگیرم. تکرار 3 از 5 من شما را نادیده میگیرم. تکرار 4 از 5
تکرار 5 از 5
[me@linuxbox ~]$ تله نمایشی
تکرار 1 از 5
تکرار 2 از 5 من شما را نادیده میگیرم. تکرار 3 از 5 من شما را نادیده میگیرم. تکرار 4 از 5
تکرار 5 از 5
همانطور که می بینیم، هر بار که کاربر تلاش می کند برنامه را قطع کند، پیام به جای آن چاپ می شود.
ساختن یک رشته برای تشکیل یک توالی مفید از دستورات ممکن است دشوار باشد، بنابراین معمول است که یک تابع پوسته را به عنوان دستور مشخص کنید. در این مثال، یک تابع پوسته جداگانه برای هر سیگنالی که باید مدیریت شود، مشخص شده است:
#! / bin / bash
# trap-demo2: کنترل ساده سیگنال نسخه ی نمایشی exit_on_signal_SIGINT () {
echo "اسکریپت قطع شد." 2>&1 خروج 0
}
exit_on_signal_SIGTERM () {
echo "اسکریپت پایان یافت." 2>&1 خروج 0
}
تله exit_on_signal_SIGINT SIGINT تله exit_on_signal_SIGTERM SIGTERM
#! / bin / bash
# trap-demo2: کنترل ساده سیگنال نسخه ی نمایشی exit_on_signal_SIGINT () {
echo "اسکریپت قطع شد." 2>&1 خروج 0
}
exit_on_signal_SIGTERM () {
echo "اسکریپت پایان یافت." 2>&1 خروج 0
}
تله exit_on_signal_SIGINT SIGINT تله exit_on_signal_SIGTERM SIGTERM
برای i در {1..5}؛ انجام دادن
echo "تکرار $i از 5" خواب 5
انجام شده
برای i در {1..5}؛ انجام دادن
echo "تکرار $i از 5" خواب 5
انجام شده
این اسکریپت دو ویژگی دارد دام دستورات، یکی برای هر سیگنال. هر تله، به نوبه خود، یک تابع پوسته را مشخص می کند که باید هنگام دریافت سیگنال خاص اجرا شود. به گنجاندن an توجه کنید خروج فرمان در هر یک از توابع کنترل سیگنال. بدون یک خروج، اسکریپت پس از تکمیل عملکرد ادامه می یابد.
وقتی کاربر فشار می دهد Ctrl-c در طول اجرای این اسکریپت، نتایج به صورت زیر است:
[me@linuxbox ~]$ trap-demo2
تکرار 1 از 5
تکرار 2 از 5 اسکریپت قطع شد.
[me@linuxbox ~]$ trap-demo2
تکرار 1 از 5
تکرار 2 از 5 اسکریپت قطع شد.
پرونده های موقت
یکی از دلایلی که کنترلکنندههای سیگنال در اسکریپتها گنجانده شدهاند، حذف فایلهای موقتی است که ممکن است اسکریپت برای نگهداری نتایج میانی در طول اجرا ایجاد کند. نامگذاری فایلهای موقت هنری است. به طور سنتی، برنامهها در سیستمهای یونیکس، فایلهای موقت خود را در آن ایجاد میکنند دایرکتوری / tmp دایرکتوری، یک دایرکتوری مشترک که برای چنین فایل هایی در نظر گرفته شده است. با این حال، از آنجایی که دایرکتوری مشترک است، نگرانی های امنیتی خاصی ایجاد می کند، به ویژه برای برنامه هایی که دارای امتیازات ابرکاربر هستند. جدا از مرحله واضح تنظیم مجوزهای مناسب برای فایل هایی که در معرض همه کاربران سیستم قرار می گیرند، دادن نام فایل های غیرقابل پیش بینی به فایل های موقت مهم است. با این کار از یک اکسپلویت معروف به a جلوگیری می شود حمله مسابقه دمایی. یکی از راههای ایجاد یک نام غیرقابل پیشبینی (اما همچنان توصیفی) انجام کاری شبیه به این است:
tempfile=/tmp/$(نام پایه $0).$$.$RANDOM
این یک نام فایل متشکل از نام برنامه، به دنبال شناسه فرآیند آن (PID) و به دنبال آن یک عدد صحیح تصادفی ایجاد می کند. با این حال توجه داشته باشید که $RAN-DOM متغیر پوسته فقط مقداری در محدوده 1-32767 برمیگرداند، که از نظر کامپیوتری محدوده زیادی نیست، بنابراین یک نمونه از متغیر برای غلبه بر یک مهاجم تعیینشده کافی نیست.
راه بهتر استفاده از mktemp برنامه (نباید با mktemp تابع کتابخانه استاندارد) برای نامگذاری و ایجاد فایل موقت. در mk- دما برنامه یک الگو را به عنوان آرگومان می پذیرد که برای ساخت نام فایل استفاده می شود. الگو باید شامل یک سری کاراکتر "X" باشد که با تعداد متناظری از حروف و اعداد تصادفی جایگزین می شوند. هر چه سری کاراکترهای "X" طولانی تر باشد، سری شخصیت های تصادفی طولانی تر است. به عنوان مثال:
tempfile=$(mktemp /tmp/foobar.$$.XXXXXXXXXX)
این یک فایل موقت ایجاد می کند و نام آن را به متغیر اختصاص می دهد tempfile. کاراکترهای "X" در الگو با حروف و اعداد تصادفی جایگزین می شوند تا نام فایل نهایی (که در این مثال شامل مقدار گسترش یافته پارامتر خاص نیز می شود. $$ برای بدست آوردن PID) ممکن است چیزی شبیه به:
/tmp/foobar.6593.UOZuvM6654
برای اسکریپت هایی که توسط کاربران معمولی اجرا می شوند، ممکن است عاقلانه باشد که از استفاده از آن خودداری کنید دایرکتوری / tmp دایرکتوری و ایجاد یک دایرکتوری برای فایل های موقت در دایرکتوری اصلی کاربر، با یک خط کد مانند زیر:
[[ -d $HOME/tmp ]] || mkdir $HOME/tmp