نحوه استفاده از Bash’s Job Control برای مدیریت فرایندهای پیش زمینه و پس زمینه
معرفی
در آموزش قبلی ، ما در مورد نحوه استفاده از دستورات ps ، kill و nice برای کنترل فرآیندهای سیستم صحبت کردیم. این راهنما نشان می دهد که چگونه bash ، سیستم لینوکس و ترمینال شما برای ارائه فرایند و کنترل کار گرد هم می آیند.
این مقاله بر مدیریت فرایندهای پیش زمینه و پس زمینه تمرکز می کند و نشان می دهد که چگونه از عملکردهای کنترل کار پوسته خود برای افزایش انعطاف پذیری در نحوه اجرای دستورات استفاده کنید.
پیش نیازها
برای پیگیری این راهنما ، به رایانه ای نیاز دارید که رابط bash shell را اجرا می کند. bash پوسته پیش فرض در بسیاری از سیستم عامل های مبتنی بر لینوکس است و در بسیاری از سیستم عامل های مشابه یونیکس از جمله macOS موجود است. توجه داشته باشید که این آموزش با استفاده از یک سرور خصوصی مجازی لینوکس که اوبونتو 20.04 را اجرا می کند ، تأیید شده است.
اگر قصد دارید از سرور راه دور برای پیروی از این راهنما استفاده کنید ، توصیه می کنیم ابتدا راهنمای راه اندازی سرور اولیه ما را تکمیل کنید. با انجام این کار شما می توانید یک محیط سرور امن-از جمله کاربر غیر root با امتیازات sudo و فایروال پیکربندی شده با UFW-را تنظیم کنید-که می توانید از آن برای ایجاد مهارت های لینوکس خود استفاده کنید.
روش دیگر ، می توانید از ترمینال تعاملی تعبیه شده در این صفحه برای آزمایش دستورات نمونه در این آموزش استفاده کنید. روی راه اندازی یک ترمینال تعاملی زیر کلیک کنید! برای باز کردن پنجره ترمینال و شروع به کار با محیط لینوکس (اوبونتو).
مدیریت فرایندهای پیش زمینه
اکثر فرایندهایی که در دستگاه لینوکس شروع می کنید در پیش زمینه اجرا می شوند. فرمان شروع به اجرا می کند و استفاده از پوسته را در طول فرآیند مسدود می کند. این فرایند ممکن است اجازه تعامل با کاربر را بدهد یا فقط یک روش را اجرا کرده و سپس خارج شود. هر خروجی به طور پیش فرض در پنجره ترمینال نمایش داده می شود. ما در بخشهای زیر روش اصلی مدیریت فرایندهای پیش زمینه را مورد بحث قرار می دهیم.
شروع یک فرایند
به طور پیش فرض ، فرایندها در پیش زمینه شروع می شوند. این بدان معناست که تا برنامه خارج نشود یا حالت خود را تغییر ندهد ، نمی توانید با پوسته تعامل داشته باشید.
برخی از دستورات پیش زمینه خیلی سریع خارج می شوند و تقریباً بلافاصله شما را به اعلان پوسته باز می گردانند. به عنوان مثال ، دستور زیر Hello World را در ترمینال چاپ می کند و سپس شما را به خط فرمان خود باز می گرداند:
echo “Hello World”
Hello World
اجرای سایر دستورات پیش زمینه بیشتر طول می کشد و دسترسی به پوسته را برای مدت زمان طولانی مسدود می کند. این ممکن است به این دلیل باشد که فرمان عملیات گسترده تری را انجام می دهد یا به این دلیل پیکربندی شده است که تا زمانی که صریحاً متوقف نشود اجرا شود یا تا زمانی که ورودی دیگر کاربر را دریافت نکند.
فرمانی که به طور نامحدود اجرا می شود ، ابزار برتر است. پس از شروع ، اجرا و به روز رسانی صفحه نمایش خود را ادامه می دهد تا زمانی که کاربر روند را خاتمه دهد:
top
با فشار دادن q می توانید از بالا خارج شوید ، اما برخی دیگر از فرایندها دارای عملکرد ترک اختصاصی نیستند. برای متوقف کردن آنها ، باید از روش دیگری استفاده کنید.
خاتمه یک فرایند
فرض کنید یک حلقه bash ساده را در خط فرمان راه اندازی می کنید. به عنوان مثال ، دستور زیر حلقه ای را شروع می کند که Hello World را هر ده ثانیه چاپ می کند. این حلقه برای همیشه ادامه می یابد ، تا زمانی که صریحاً خاتمه یابد:
while true; do echo “Hello World”; sleep 10; done
بر خلاف بالا ، حلقه هایی مانند این کلید “خروج” ندارند. شما باید با ارسال سیگنال ، روند را متوقف کنید. در لینوکس ، کرنل می تواند سیگنال هایی را به فرآیندهای در حال اجرا ارسال کند ، به عنوان یک درخواست برای خروج یا تغییر حالت. پایانه های لینوکس معمولاً طوری تنظیم شده اند که وقتی کاربر کلید ترکیبی CTRL + C را فشار می دهد ، سیگنال “SIGINT” (مخفف “قطع سیگنال”) را به فرایند پیش زمینه فعلی ارسال می کند. سیگنال SIGINT به برنامه می گوید که کاربر با استفاده از صفحه کلید درخواست خاتمه داده است.
برای توقف حلقه ای که شروع کرده اید ، کلید CTRL را نگه دارید و کلید C را فشار دهید:
CTRL + C
حلقه خارج می شود و کنترل را به پوسته باز می گرداند.
سیگنال SIGINT ارسال شده توسط ترکیب CTRL + C یکی از سیگنال های زیادی است که می تواند به برنامه ها ارسال شود. اکثر سیگنالها دارای ترکیب صفحه کلید مرتبط با آنها نیستند و باید با استفاده از دستور kill ارسال شوند ، که بعداً در این راهنما توضیح داده می شود.
تعلیق فرآیندها
همانطور که قبلاً ذکر شد ، فرایند پیش زمینه دسترسی به پوسته را در طول مدت اجرای آنها مسدود می کند. اگر یک فرایند را در پیش زمینه شروع کنید ، اما بعد متوجه شوید که به ترمینال نیاز دارید ، چطور؟
سیگنال دیگری که می توانید ارسال کنید ، سیگنال “SIGTSTP” است. SIGTSTP مخفف کلمه “stop terminal signal” است و معمولاً به عنوان شماره سیگنال 20 نشان داده می شود. هنگامی که CTRL + Z را فشار می دهید ، ترمینال شما فرمان “تعلیق” را ثبت می کند ، که سپس سیگنال SIGTSTP را به فرایند پیش زمینه ارسال می کند. در اصل ، این امر اجرای فرمان را متوقف کرده و کنترل را به ترمینال باز می گرداند.
برای نشان دادن تصویر ، از ping برای اتصال به google.com هر 5 ثانیه استفاده کنید. دستور زیر قبل از دستور ping فرمان دارد ، که به شما امکان می دهد از نام مستعار پوسته ای که به طور مصنوعی حداکثر تعداد فرمان را تعیین می کند ، دور بزنید:
command ping -i 5 google.com
به جای خاتمه فرمان با CTRL + C ، به جای آن CTRL + Z را فشار دهید. با این کار خروجی به این شکل برمی گردد
[1]+ Stopped ping -i 5 google.com
فرمان پینگ به طور موقت متوقف شده است و به شما امکان می دهد دوباره به یک اعلان پوسته دسترسی پیدا کنید. برای نشان دادن این مورد می توانید از ابزار پردازش ps استفاده کنید:
ps T
PID TTY STAT TIME COMMAND
26904 pts/3 Ss 0:00 /bin/bash
29633 pts/3 T 0:00 ping -i 5 google.com
29643 pts/3 R+ 0:00 ps t
این خروجی نشان می دهد که فرآیند پینگ هنوز فهرست شده است ، اما ستون “STAT” یک “T” در آن دارد. در صفحه ps ps ، این بدان معناست که شغلی که “با سیگنال کنترل کار متوقف شده است”.
در این راهنما نحوه تغییر حالتهای فرآیند در عمق بیشتر توضیح داده می شود ، اما در حال حاضر می توانید با تایپ کردن دستور فرمان را دوباره در پیش زمینه از سر بگیرید.
fg
پس از از سرگیری روند ، آن را با CTRL + C خاتمه دهید:
مدیریت فرایندهای پیشین
جایگزین اصلی برای اجرای یک فرایند در پیش زمینه این است که اجازه دهید در پس زمینه اجرا شود. یک فرایند پس زمینه با ترمینال خاصی که آن را شروع کرده است مرتبط است ، اما دسترسی به پوسته را مسدود نمی کند. در عوض ، در پس زمینه اجرا می شود و کاربر را قادر می سازد تا در حین اجرا فرمان با سیستم تعامل داشته باشد.
به دلیل نحوه تعامل یک فرایند پیش زمینه با ترمینال خود ، برای هر پنجره ترمینال تنها یک فرایند پیش زمینه وجود دارد. از آنجا که فرآیندهای پس زمینه کنترل را بلافاصله به پوسته باز می گردانند بدون اینکه منتظر بمانیم تا فرآیند تکمیل شود ، بسیاری از فرایندهای پس زمینه می توانند همزمان اجرا شوند.
شروع فرآیندها
می توانید با افزودن یک کاراکتر ampersand (&) به انتهای دستورات خود ، یک فرایند پس زمینه را شروع کنید. این به پوسته می گوید منتظر نمانید تا فرآیند به اتمام برسد ، بلکه باید اجرا را آغاز کرده و بلافاصله کاربر را به یک اعلان بازگرداند. خروجی فرمان همچنان در ترمینال نمایش داده می شود (مگر اینکه هدایت شود) ، اما با ادامه روند پس زمینه می توانید دستورات بیشتری را تایپ کنید.
به عنوان مثال ، می توانید همان فرایند پینگ را از قسمت قبلی در پس زمینه با تایپ کردن شروع کنید:
command ping -i 5 google.com &
سیستم کنترل کار bash خروجی را به صورت زیر برمی گرداند:
[1] 4287
سپس خروجی معمولی را از دستور ping دریافت خواهید کرد:
PING google.com (74.125.226.71) 56(84) bytes of data.
64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=1 ttl=55 time=12.3 ms
64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=2 ttl=55 time=11.1 ms
64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=3 ttl=55 time=9.98 ms
با این حال ، شما همچنین می توانید دستورات را همزمان تایپ کنید. خروجی فرایند پس زمینه در بین ورودی و خروجی فرایندهای پیش زمینه شما مخلوط می شود ، اما در اجرای فرایندهای پیش زمینه تداخلی ایجاد نمی کند.
لیست فرایندهای پس زمینه
برای لیست تمام فرآیندهای متوقف شده یا پس زمینه ، می توانید از دستور jobs استفاده کنید:
jobs
اگر هنوز فرمان پینگ قبلی را در پس زمینه اجرا کرده اید ، خروجی فرمان jobs شبیه این خواهد بود:
[1]+ Running command ping -i 5 google.com &
این نشان می دهد که شما در حال حاضر یک فرایند تک پس زمینه در حال اجرا دارید. [1] مشخصات کار یا شماره کار فرمان را نشان می دهد. می توانید با سایر دستورات کنترل کار و فرآیند ، مانند kill ، fg و bg ، با شماره قبلی با علامت درصد ، این مورد را ارجاع دهید. در این مورد ، شما این شغل را٪ 1 ارجاع می دهید.
توقف فرآیندهای پیش زمینه
می توانید فرایند فعلی پس زمینه را از چند طریق متوقف کنید. ساده ترین راه این است که از دستور kill با شماره کار مربوطه استفاده کنید. برای مثال ، می توانید فرایند پس زمینه در حال اجرا را با تایپ کردن از بین ببرید:
kill %1
بسته به نحوه پیکربندی پایانه شما ، بلافاصله یا دفعه بعد که ENTER را فشار می دهید ، وضعیت پایان کار در خروجی شما ظاهر می شود:
[1]+ Terminated command ping -i 5 google.com
اگر دوباره فرمان jobs را بررسی کنید ، هیچ کار فعلی وجود نخواهد داشت.
تغییر حالتهای فرآیند
کنون که می دانید چگونه مراحل را در پس زمینه شروع و متوقف کنید ، می توانید با تغییر وضعیت آنها آشنا شوید.
این راهنما قبلاً یکی از روشهای تغییر وضعیت یک فرآیند را توضیح داده است: توقف یا تعلیق یک فرآیند با CTRL + Z. هنگامی که فرآیندها در این حالت متوقف شده هستند ، می توانید یک فرایند پیش زمینه را به پس زمینه یا برعکس منتقل کنید.
انتقال فرآیندهای پیش زمینه به پس زمینه
اگر فراموش کنید که یک فرمان را با & هنگام شروع به کار خاتمه دهید ، همچنان می توانید روند را به پس زمینه منتقل کنید.
اولین قدم متوقف کردن مجدد فرآیند با CTRL + Z است. هنگامی که فرآیند متوقف شد ، می توانید از دستور bg برای شروع مجدد آن در پس زمینه استفاده کنید:
bg
دوباره خط وضعیت شغل را دریافت خواهید کرد ، این بار با ضمیمه اصلی اضافه شده است:
[1]+ ping -i 5 google.com &
به طور پیش فرض ، دستور bg آخرین فرآیند متوقف شده را اجرا می کند. اگر چندین فرآیند را در یک ردیف بدون شروع مجدد متوقف کرده اید ، می توانید یک پروسه خاص را با شماره شغل آن ارجاع دهید تا روند صحیح به پس زمینه منتقل شود.
توجه داشته باشید که نمی توان همه دستورات را پس زمینه کرد. اگر برخی از فرایندها تشخیص دهند که با ورودی و خروجی استاندارد خود مستقیماً به یک ترمینال فعال متصل شده اند ، به طور خودکار خاتمه می یابد.
انتقال فرایندهای پیش زمینه به پیش زمینه
همچنین می توانید فرایندهای پس زمینه را با تایپ fg به پیش زمینه منتقل کنید:
fg
این کار بر اساس آخرین فرایند پس زمینه شما (که در خروجی فرمان jobs + نشان داده شده است) عمل می کند. بلافاصله این روند را متوقف می کند و آن را در پیش زمینه قرار می دهد. برای تعیین کار متفاوت ، از شماره شغل آن استفاده کنید:
fg %2
هنگامی که یک کار در پیش زمینه قرار دارد ، می توانید آن را با CTRL + C بکشید ، بگذارید تکمیل شود ، یا تعلیق کرده و دوباره به پس زمینه منتقل کنید
برخورد با SIGHUPs
فرایندی که در پس زمینه باشد یا در پیش زمینه ، نسبتاً محکمی با نمونه پایانی دارد که آن را آغاز کرده است. هنگامی که یک ترمینال بسته می شود ، معمولاً یک سیگنال SIGHUP به تمام فرایندهایی (پیش زمینه ، پس زمینه یا متوقف شده) که به ترمینال متصل هستند ارسال می کند. این نشان می دهد که فرآیندها خاتمه می یابد زیرا ترمینال کنترل آنها به زودی در دسترس نخواهد بود.
هر چند ممکن است مواقعی وجود داشته باشد که بخواهید یک ترمینال را ببندید اما فرایندهای پیش زمینه را در حال اجرا نگه دارید. روشهای مختلفی برای انجام این کار وجود دارد. یکی از روش های انعطاف پذیرتر استفاده از چند ضلعی ترمینال مانند صفحه نمایش یا tmux است. راه حل دیگر استفاده از ابزاری است که قابلیت جدا شدن صفحه و tmux را مانند dtach ارائه می دهد.
با این حال ، این همیشه یک گزینه نیست. گاهی اوقات این برنامه ها در دسترس نیستند یا شما قبلاً فرایندی را شروع کرده اید که باید به آن ادامه دهید. گاهی اوقات اینها ممکن است برای آنچه شما باید انجام دهید بیش از حد باشد.
استفاده از nohup
اگر هنگام شروع فرآیند می دانید که می خواهید ترمینال را قبل از اتمام فرآیند ببندید ، می توانید آن را با استفاده از دستور nohup شروع کنید. این امر باعث می شود فرآیند شروع شده در برابر سیگنال SIGHUP مصون باشد. با بسته شدن ترمینال به کار خود ادامه می دهد و مجدداً به عنوان فرزند سیستم init تعیین می شود:
nohup ping -i 5 google.com &
با این کار خطی مانند تصویر زیر برمی گردد که نشان می دهد خروجی دستور در فایلی به نام nohup.out نوشته می شود:
nohup: ignoring input and appending output to ‘nohup.out’
این فایل در صورت قابل نوشتن در فهرست فعلی کار شما قرار می گیرد ، اما در غیر این صورت در فهرست اصلی شما قرار می گیرد. این امر برای اطمینان از از بین رفتن خروجی در صورت بسته بودن پنجره ترمینال است.
اگر پنجره ترمینال را ببندید و پنجره دیگری را باز کنید ، فرآیند همچنان اجرا می شود. شما آن را در خروجی فرمان jobs پیدا نمی کنید زیرا هر نمونه ترمینال صف شغل مستقل خود را حفظ می کند. بستن ترمینال باعث از بین رفتن کار پینگ می شود حتی اگر روند پینگ همچنان در حال اجرا باشد.
برای از بین بردن روند پینگ ، باید شناسه پردازش آن (یا “PID”) را پیدا کنید. می توانید این کار را با دستور pgrep انجام دهید (دستور pkill نیز وجود دارد ، اما این روش دو قسمتی تضمین می کند که شما فقط فرایند مورد نظر را از بین می برید). برای جستجوی اجرایی از pgrep و پرچم -a استفاده کنید:
pgrep -a ping
7360 ping -i 5 google.com
سپس می توانید با مراجعه به PID برگشتی ، که در ستون اول است ، فرآیند را بکشید:
kill 7360
اگر دیگر نیازی به فایل nohup.out ندارید ، ممکن است بخواهید آن را حذف کنید.
استفاده از disown
دستور nohup مفید است ، اما تنها در صورتی که بدانید در زمان شروع فرآیند به آن نیاز خواهید داشت. سیستم کنترل کار bash روش های دیگری را برای دستیابی به نتایج مشابه با دستور disown داخلی ارائه می دهد.
فرمان disown در پیکربندی پیش فرض خود ، یک کار را از صف مشاغل یک ترمینال حذف می کند. این بدان معناست که دیگر نمی توان آن را با استفاده از مکانیزم های کنترل شغل که قبلاً در این راهنما توضیح داده شد مدیریت کرد ، مانند fg ، bg ، CTRL + Z ، CTRL + C. در عوض ، کار بلافاصله از لیست در خروجی مشاغل حذف می شود و هیچ دیگر با ترمینال ارتباط دارد
فرمان با تعیین یک شماره کار فراخوانی می شود. به عنوان مثال ، برای رد فوراً شغل 2 ، می توانید تایپ کنید:
disown %2
پس از بسته شدن ترمینال کنترل ، این فرایند در وضعیتی قرار می گیرد که برخلاف فرآیند nohup نیست. استثنا این است که هر خروجی در صورت بسته شدن ترمینال کنترل از بین نمی رود اگر به یک فایل هدایت نشده باشد.
معمولاً ، اگر بلافاصله پنجره ترمینال خود را نبندید ، نمی خواهید روند را به طور کامل از کنترل کار حذف کنید. می توانید به جای آن پرچم -h را به فرآیند رد کردن منتقل کنید تا روند را نادیده بگیرید و سیگنال های SIGHUP را نادیده بگیرید ، اما در غیر این صورت به عنوان یک کار معمولی ادامه دهید:
disown -h %1
در این حالت ، می توانید از مکانیزم های عادی کنترل شغل برای کنترل روند تا بستن ترمینال استفاده کنید. پس از بستن ترمینال ، اگر در هنگام راه اندازی مجدد فایل به آن هدایت نشوید ، یکبار دیگر با یک فرایند بدون خروجی گیر خواهید کرد.
برای حل این مشکل ، می توانید خروجی فرآیند خود را پس از اجرا مجدد تغییر مسیر دهید. این خارج از محدوده این راهنما است ، اما این پست توضیح می دهد که چگونه می توانید این کار را انجام دهید.
با استفاده از huponexit Shell Option
bash راه دیگری برای جلوگیری از مشکل SIGHUP برای فرآیندهای کودک دارد. گزینه پوسته huponexit کنترل می کند که آیا bash هنگام خروج سیگنال SIGHUP را به فرزند خود ارسال می کند یا خیر.
با وجود هشدارهای فوق الذکر ، مدیریت گزینه huponexit شاید یکی از ساده ترین ها برای مدیریت باشد. با تایپ کردن می توانید روشن یا خاموش بودن این ویژگی را تعیین کنید:
shopt huponexit
برای روشن کردن آن تایپ کنید:
shopt -s huponexit
اکنون ، اگر جلسه خود را با تایپ کردن exit خارج کنید ، همه فرآیندهای شما به کار خود ادامه می دهند:
exit
این گزینه در مورد خروجی برنامه به عنوان آخرین گزینه دارای هشدار است ، بنابراین مطمئن شوید که قبل از بستن ترمینال ، خروجی فرآیندهای خود را تغییر داده اید ، اگر این مهم است.
نتیجه
یادگیری کنترل شغل و نحوه مدیریت فرایندهای پیش زمینه و پس زمینه هنگام اجرای برنامه ها در خط فرمان به شما انعطاف پذیری بیشتری می بخشد. به جای باز کردن بسیاری از پنجره های ترمینال یا جلسات SSH ، اغلب می توانید با توقف زودهنگام فرآیندها یا انتقال آنها به پس زمینه در صورت لزوم ، کار کنید.
https://vpsgol.net/product/vps-germany/
https://vpsgol.net/product/vps-usa/
https://vpsgol.net/product/vps-france/
https://vpsgol.net/product/vps-canada/
https://vpsgol.net/product/vps-poland/
https://vpsgol.net/product/vps-netherlands/
https://vpsgol.net/product/vps-england/