سرویس منیجر چیست ؟ (بررسی و تفاوت sysV و systemd)

در سیستم عامل های مبتنی بر لینوکس، سرویس منیجر (Service Manager) نقش کلیدی در مدیریت فرآیند ها و سرویس های سیستم ایفا می کند. این مورد ، که اغلب به عنوان سیستم init شناخته می شود، مسئولیت راه اندازی، نظارت و توقف سرویس ها را بر عهده دارد. سرویس ها شامل برنامه هایی مانند سرورهای وب، پایگاه های داده ،سرویس های اتصال از راه دور ، سرویس های شبکه و غیره هستند که در پس زمینه اجرا می شوند. سرویس منیجر نخستین پراسسی است که پس از بارگذاری هسته (kernel) لینوکس اجرا می شود و با شماره پراسس (PID) برابر با 1 شناخته می شود. این سیستم وابستگی های بین سرویس ها را مدیریت کرده، سرعت راه اندازی سیستم را بهینه می کند و در صورت بروز خطا، امکان بازیابی را فراهم می آورد. بدون یک سرویس منیجر کارآمد و قدرتمند، عملیات سیستم عامل مختل می شود . در این مقاله، ابتدا به تعریف و نقش سرویس منیجر می پردازیم، و سپس با SysV init و systemd آشنا می شویم و تفاوت های آن ها را مقایسه می کنیم و در نهایت، نحوه کار با هر کدام را با مثال های عملی توضیح می دهیم. تمرکز بر جنبه های فنی و کاربردی است تا برای کاربران مبتدی و پیشرفته مفید باشد
.
بخش 1 : تعریف و نقش های سرویس منیجر در لینوکس
یک سرویس منیجر هسته مدیریت سیستم در لینوکس است. این سیستم پس از بوت هسته یا همان کرنل ، سرویس های ضروری را راه اندازی و اصطلاحا (up) می کند و بر عملکرد آن ها نظارت دارد. نقش های اصلی آن عبارتند از:
1- راه اندازی سیستم: شروع فرآیند های اولیه و انتقال سیستم از حالت خاموش به عملیاتی.
2- مدیریت وابستگی ها: اطمینان از اجرای سرویس ها به ترتیب صحیح، مانند راه اندازی شبکه پیش از سرور وب.
3- نظارت و بازیابی: تشخیص خرابی سرویس ها و راه اندازی مجدد آن ها.
4- ثبت وقایع: نگهداری لاگ ها برای تحلیل عملکرد سیستم.
5- کنترل منابع: تخصیص منابع مانند CPU و حافظه به فرآیند ها پراسس ها.
بخش 2 : تاریخچه سرویس منیجر ها در لینوکس
سرویس منیجر ها، که به عنوان سیستم های init شناخته می شوند، بخش حیاتی مدیریت لینوکس هستند. تاریخچه آن ها از یونیکس آغاز شد و با پیچیده تر شدن سیستم ها تکامل یافت تا نیاز های مدرن را برآورده کند.
در دهه 1970 ، در Research Unix، سیستم init یک اسکریپت ساده بود که توسط Ken Thompson و Dennis Ritchie در آزمایشگاه های بل طراحی شد. این سیستم process های اولیه مانند شل را اجرا می کرد و به عنوان ” reaper ” فرآیند های مرده عمل می نمود (reaper یک اصطلاح فنی در سیستم عامل های شبه یونیکس است و به فرآیندی اشاره دارد که وظیفه دارد process های فرزند (child processes) مرده را جمع آوری کند و آن ها را از حافظه برای آزاد کردن منابع پاک کند .). این رویکرد ساده، پایه سرویس منیجر ها شد، اما برای سیستم های پیچیده کافی نبود.
در اواخر دهه 1970 ، BSD Unix فایل /etc/rc را معرفی کرد که اسکریپتی واحد برای راه اندازی سرویس ها بود. بعدها، /etc/rc.local برای سفارشی سازی اضافه شد. این مدل BSD-style، که هنوز در سیستم FreeBSD استفاده می شود، به ساده بودن تاکید دارد ، اما موجب بهبود مدیریت وابستگی ها نشد .
بخش 3 : انواع سرویس منیجر ها
سرویس منیجرها انواع مختلفی دارند که در ابتدا ،در دهه 1980 ، AT&T UNIX System V، سیستم SysV init را با مفهوم سطوح اجرا (runlevels) معرفی کرد. این سیستم امکان اجرای سیستم در حالت های مختلف (مانند تک کاربره یا چند کاربره) را فراهم کرد. SysV init در لینوکس اولیه (۱۹۹۱) پذیرفته شد و در توزیع هایی مانند Debian، Red Hat و Slackware رایج شد . اسکریپت های سرویس در دایرکتوری هایی مانند /etc/rc.d مدیریت می شدند،بعد ها به دلیل قدیمی بودن این سیستم در راه اندازی سریال سرویس ها و مدیریت دستی وابستگی ها محدودیت هایی ایجاد کرد و به دلیل عدم توانایی انجام برخی کار ها در سیستم های نسل جدید تر و همینطور محدودیت هایی که در این سیستم وجود داشت ،تصمیم بر توسعه یک سیستم سرویس منیجر جدید شد که شرکت های مختلف برای این کار دست شدند و سرویس منیجر های متفاوتی را معرفی کردند .
با پیچیده تر شدن سیستم ها، SysV init نا کارآمد شد. در سال 2006 ، Upstart توسط Canonical (شرکت توسعه دهنده دیسترو Ubuntu) برای Ubuntu توسعه یافت. این سیستم رویداد محور، سرویس ها را به صورت موازی بر اساس رویداد هایی مانند اتصال دستگاه راه اندازی می کرد. Upstart در Fedora و RHEL 6 نیز استفاده شد، اما نبود کنترل منابع پیشرفته، آن را محدود کرد.
در سال 2010 ، Lennart Poettering در Red Hat، سیستم systemd را معرفی کرد. این سیستم فراتر از init بود و شامل ابزار هایی برای لاگینگ (journald)، مدیریت شبکه و کنترل منابع با cgroups بود. systemd با راه اندازی موازی و مدیریت وابستگی ها، زمان بوت را کاهش داد. در Fedora 15 (2011)، Debian 8 (2015) و Ubuntu 15.04 (2015) نیز این سیستم پذیرفته شد. با این حال، به دلیل پیچیدگی و نقض فلسفه یونیکس ، بحث برانگیز شد و فورک و دیسترو هایی مانند Devuan (بدون systemd) ایجاد شدند.
امروز، systemd در بیش از ۹۰ درصد توزیع ها غالب است، اما SysV init در سیستم های قدیمی یا سبک مانند Slackware باقی مانده. سیستم های جایگزین مانند OpenRC و runit نیز در توزیع های خاص استفاده می شوند. این تکامل، پاسخی به نیاز های رایانش ابری و کانتینریزاسیون است و در آینده ممکن است شامل فناوری هایی مانند eBPF باشد.
این تغییرات و معرفی سرویس منیجر های مختلف، نشان دهنده روند تکامل مدیریت فرایند ها در سیستم عامل های شبه یونیکس است. هر نسل از این ابزار ها با هدف بهبود سرعت، انعطاف پذیری و سادگی در مدیریت سرویس ها معرفی شد تا نیاز های جدید سیستم های مدرن را برطرف کند و محدودیت های نسخه های قبلی را کاهش دهد.
برای مثال Upstart که توسط شرکت Canonical (شرکت توسعه دهنده دیسترو Ubuntu) معرفی شد و مدت ها در توزیع اوبونتو پیش فرض بود .
یا OpenRC که توسط Roy Marples برای Gentoo Linux توسعه داده شد و همینطور runit و s6 و Epoch و غیره .
اما در نهایت شرکت Red Hat سرویس منیجر systemd را معرفی کرد که یک سیستم مدرن و جامع و بسیار قدرتمند است که در نهایت توانست جایگزین تمام سرویس منیجر های بالا شود و به عنوان سرویس منیجر پیش فرض در بسیاری از دیسترو های امروزی لینوکس وجود داشته باشد .
امروزه ، systemd در بیش از 90 درصد توزیع ها سرویس منیجر پیش فرض است، در حالی که SysV init در سیستم های قدیمی تر یا سبک باقی مانده.
می توانید در این مقاله ( انواع توزیع های لینوکس ) درباره ی توزیع های لینوکس بیشتر بخوانید .
البته انتخاب سرویس منیجر همانطور که در بالا اشاره شد بر اساس توزیع لینوکس و کاربرد ما ممکن است متفاوت باشد و تأثیر مستقیمی بر کارایی سیستم دارد.
برای مثال در محیط های سروری، سرویس منیجر زمان توقف را کاهش می دهد، در حالی که در سیستم های دسکتاپ، سرعت بوت را افزایش می بخشد. درک این سیستم برای administrators سیستم ضروری است.
بخش 3 : SysV init – توصیف و نحوه عملکرد
سیستم سرویس منیجر SysVinit یکی از قدیمی ترین init system های لینوکس است که از System V در یونیکس به ارث رسیده است . وظیفه اصلی این سیستم این است که بعد از بوت شدن کرنل، اولین پروسه ی سیستم (PID1) را او اجرا کند و با خواندن تنظیمات و فایل های پیکر بندی، سرویس ها و محیط سیستم را مدیریت و برای اجرا آماده کند.
می توانید در مورد نحوه کار sysV init به عنوان اولین پراسس سیستم در این مقاله <init Program> بیشتر بخوانید .
این سرویس منیجر بر پایه سطح های متفاوتی که به عنوان ( run level ) شناخته می شوند کار می کند .ران لول ها (Run levels) نشان دهنده وضعیت اجرایی سیستم هستند ; یعنی سیستم در چه حالتی بوت شده و چه سرویس هایی باید اجرا شوند. run level ها حالت های کاری متفاوتی هستند که در هر کدام از آن ها مشخص می شود سیستم ما با چه سرویس هایی start شود . در واقع یعنی هر ران لول مجموعه ای از اسکریپت ها را از مسیر خاصی اجرا یا متوقف می کند تا سیستم را به حالت مشخصی ببرد (مثل multi-user mode، rescue mode و غیره). در حالت کلی ما در سیستم اینیت 7 رانلول داریم که از عدد 0 تا 6 است و هر کدام از این اعداد به حالت های مختلف کاری نسبت داده می شود . در ادامه این حالت های کاری مختلف را مشاهده می کنیم .
ران لول ها در ابتدا در سیستم های debian base و سیستم های Red Hat base متفاوت بود که در هر کدام به شکل زیر بود :
ران لول ها در سیستم های Red Hat based (مثل RHEL, CentOS, Fedora قدیمی):
– 0 = (Halt) حالت خاموش کردن سیستم
– 1 = (Single User) حالت تعمیر تک کاربره
– 2 = (Multi User) حالت چند کاربره و بدون شبکه
– 3 = (Multi User) حالت جند کاربره با شبکه بدون واسط گرافیگی
– 4 = (Free for User) رزرو شده برای سفارشی سازی توسط کاربر
– 5 = (Graphical Mode + Multi User) حالت چند کاربره ، گرافیکی با شبکه
– 6 = (Reboot) حالت ریبوت سیستم
در سیستم های Red Hat Based مدیریت اسکریپت ها و رانلول ها در مسیر زیر انجام می شد :
/etc/rc.d/rc#.d/
(# همان شمارهی ران لول است)
و فایل کانفیگ و تنظیم ران لول پیش فرض در مسیر زیر قرار داشت :
/etc/inittab
ران لول ها در سیستم های Debian based (مثل Ubuntu, Kali, Linux Mint) :
در دبیان بیس ها نیز منطق تقریبا مشابه با Red Hat Based ها دارند ، اما با تفاوت های جزئی در ساختار و کاربرد وجود دارد .
– 0 = (Halt) حالت خاموش کردن سیستم
– 1 = (Single User) حالت تعمیر تک کاربره
– 2 = (Multi User) حالت جند کاربره با شبکه
– 3 = (Free For User) در دبیان معمولا مانند ران لول 2 عمل می کند
– 4 = (Free For User) در دبیان معمولا مانند ران لول 2 عمل می کند
– 5 = (Free For User) در دبیان معمولا مانند ران لول 2 عمل می کند
– 6 = (Reboot) حالت ریبوت سیستم
در سیستم های Debian based مدیریت اسکریپت ها و ران لول ها در مسیر متفاوتی از Red Hat Based ها انجام می شد :
/etc/rc#.d/
(# همان شمارهی ران لول است)
و مسیر کانفیگ و تنظیم ران لول پیش فرض هم مشابه با همان مسیر رد هت است :
/etc/inittab
در سیستم اینیت همانطور که در بالا اشاره شد ، برای هر run level، دایرکتوری هایی مثل /etc/rc.d/rc#.d (که # شماره runlevel هست) وجود دارد. در داخل این دایرکتوری ها ، لینک های سمبولیک ( sym link ) به اسکریپت های سرویس در /etc/init.d هستند . لینک هایی که با S شروع می شوند برای start کردن آن سرویس و لینک هایی که با K شروع می شوند برای kill/stop کردن آن سرویس استفاده می شوند ، و یک عدد دو رقمی برای ترتیب و اولویت بندی استاپ یا استارت کردن سرویس ها بعد از حرف کلیدی قرار میگیرد ( مثل S10network برای شروع شبکه در اولویت 10 ).
وقتی run level تغییر می کند ، init همه ی اسکریپت های K را برای stop کردن سرویس ها اجرا می کند ، سپس S ها رو برای start اجرا می کنید .
نحوه کار با SysV init
برای بررسی سیستم خود می توانید ، از دستور ps -p 1 استفاده کنید تا PID 1 را ببینید.
نحوه کنترل init و رانلول ها در توزیع های مختلف گاها متفاوت است و برای هر توزیع ممکن است ابزار متفاوتی وجود داشته باشد .
در بخش پایین به بررسی برخی از دستورات مدیریتی sysV init می پردازیم :
1 – دستور : init X
به جای X شماره ران لول مد نظر برای تغییر مود سیستم به ران لول مشخص شده .
2 – دستور : runlevel
برای نمایش شماره ران لول قبلی و شماره ی ران لول فعلی که سیستم بر روی آن حالت اجرا شده است .
3 – دستور : service X start | stop | restart | status | reload
برای مدیریت سرویس ها ( شامل استارت کردن ، استاپ کردن ، ری استارت کردن و نمایش وضعیت فعلی سرویس ) . به جای X نام سرویس مد نظر را بنویسید .
4 – دستور : chkconfig
برای مدیریت و کنترل سرویس ها و دیمن ها در زمان بوت سیستم (در سیستم های Red Hat Based)
5 – دستور : udate-rc.d
برای مدیریت و کنترل سرویس ها و دیمن ها در زمان بوت سیستم (در سیستم های Debian Based)
6 – دستور : etc/init.d/X start | stop | restart | status | reload/
برای مدیریت سرویس ها ( شامل استارت کردن ، استاپ کردن ، ری استارت کردن و نمایش وضعیت فعلی سرویس ) . به جای X نام سرویس مد نظر را بنویسید . ( در سیستم های LSB)
مفهوم سرویس و دیمن ها در سیستم های init (مثل SysV)
در سیستم عامل های شبه یونیکس، مفهومی به نام سرویس (Service) یا عمدتا دیمن (Daemon) وجود دارد که هسته ی اصلی عملکرد های پس زمینه ای سیستم را تشکیل می دهد. دیمن در واقع نوعی پردازش بلند مدت (long running process) است که بدون نیاز به تعامل مستقیم کاربر، وظایف خاصی را به صورت مداوم در پس زمینه اجرا می کند. برای مثال، سرویسی مانند sshd مسئول مدیریت ارتباطات ورودی SSH است و همواره در پس زمینه به صورت پیش فرض در حال گوش دادن (listening) به پورت 22 یا پورت دیگری که توسط ادمین سیستم برای سرویس ssh در نظر گرفته شده است می باشد ، تا در صورت ورود یک اتصال جدید، پاسخ گو باشد. به همین شکل، سرویس های دیگری نظیر crond که زمان بندی اجرای دستورات را مدیریت می کند یا nginx که به درخواست های HTTP پاسخ می دهد ، وجود دارند . وجه اشتراک تمام این سرویس ها، ماهیت مستقل و دائمی آن هاست؛ یعنی حتی در نبود کاربر فعال، همچنان به کار خود ادامه می دهند.
در معماری سنتی سیستم های لینوکسی که مبتنی بر سرویس منیجر SysV init (System V init) هستند، همانطور که در بالاتر اشاره شد ، مدیریت و راه اندازی این سرویس ها توسط مجموعه ای از اسکریپت های پوسته (shell scripts) انجام می شود که معمولاً در مسیر /etc/init.d/ قرار دارند. هر یک از این اسکریپت ها نشان دهنده یک سرویس است و شامل دستوراتی برای عملیات های پایه ای نظیر start، stop، restart و status و گاهی reload می باشد. مکانیزم کاری init در این ساختار به این صورت است که هنگام بوت شدن سیستم، بر اساس runlevel تعیین شده (که در فایل هایی مثل etc/inittab/ تعریف می شود)، init اسکریپت های مربوط به آن سطح اجرایی را به ترتیب مشخص اجرا می کند. برای مثال، در runlevel 3 (که معمولاً مربوط به حالت multi-user بدون رابط گرافیکی است)، init ممکن است سرویس های شبکه، لاگگیری، و سرویس های essential سیستمی را یکی پس از دیگری اجرا کند.
نکته ی کلیدی در SysVinit این است که هر سرویس عملا توسط همین اسکریپت ها مدیریت می شود و هیچ مفهومی از dependency resolution یا parallel startup در ساختار ذاتی آن وجود ندارد. بنابراین، اگر سرویسی برای اجرا نیاز به سرویس دیگری داشته باشد، مدیر سیستم باید ترتیب اجرای آن ها را به صورت دستی در نام فایل ها (با پیشون هایی مانند S20network یا S30sshd ) مشخص کند. این مدل گرچه ساده است، اما در سیستمهای مدرن با تعداد زیاد سرویس، مقیاسپذیری کمی دارد.
– برای درک بهتر منطق کاری سرویس ها در سرویس منیجر SysVinit، اسکریپت زیر نمونه ای از یک سرویس ساده را نشان می دهد:
#!/bin/sh case "$1" in start) echo "Service Started !" /usr/bin/myservice & ;; stop) echo "Service Stopped !" killall myservice ;; restart) $0 stop $0 start ;; *) echo "Options : $0 {start|stop|restart}" ;; esac
در این مثال، رفتار سرویس به صورت کامل توسط خود اسکریپت تعریف شده است. هنگامی که دستور start اجرا می شود، برنامه ی اصلی ( /usr/bin/myservice ) در پس زمینه راه اندازی می گردد. در مقابل، دستور stop با استفاده از killall تمام پردازش هایی که با نام myservice در حال اجرا هستند را خاتمه می دهد. دستور restart نیز در واقع ترکیبی از دو فرمان قبلی است که ابتدا سرویس را متوقف و سپس مجددا راه اندازی می کند.
اگرچه این اسکریپت در ظاهر ساده است، اما نمایانگر منطق سنتی SysVinit می باشد که هیچ لایه ی انتزاعی بین سرویس و سیستم وجود ندارد؛ خود اسکریپت مستقیما با پردازش ها و سیگنال ها کار می کند. در سیستم های واقعی، نسخه های پیشرفته تر چنین اسکریپت هایی معمولا از فایل های PID در /var/run/ استفاده می کنند تا تنها همان پردازش اصلی سرویس (و نه همه ی پردازش های هم نام) متوقف شود، و همچنین کد های بازگشتی (exit codes) مشخصی برای اعلام وضعیت موفقیت یا شکست عملیات ارائه دهند.
در نتیجه، سرویس در سرویس منیجر SysVinit در اصل چیزی جز یک اسکریپت کنترل پردازش نیست که وظیفه ی راه اندازی، پایش و خاتمه ی یک دیمن را بر عهده دارد. init تنها نقش یک orchestrator ابتدایی را بازی می کند: اسکریپت ها را در ترتیب از پیش تعیین شده اجرا کرده و هیچ درکی از وضعیت، وابستگی یا رفتار در حال اجرای سرویس ها ندارد. این ساختار ساده، نقطه ی شروع سیستم های سرویس منیجر مدرن تری مانند systemd بود که با هدف مدیریت وابستگی ها، مانیتورینگ پردازش ها و بهبود زمان بوت توسعه یافت.
بخش 4 : Systemd – توصیف و نحوه عملکرد
سیستم Systemd یک سیستم init مدرن است که جایگزین SysV در اکثر توزیع ها شده. این سیستم فراتر از init عمل کرده و مجموعه ای از ابزار ها را ارائه می دهد.
توصیف Systemd
سیستم systemd نسل جدید سیستم های init در لینوکس است که به منظور رفع محدودیت ها و افزایش کارایی مدل سنتی SysVinit طراحی و پیاده سازی شد. وظیفه ی systemd، مانند init سنتی، این است که پس از بوت شدن کرنل به عنوان پروسه ی اولیه با PID 1 اجرا شود، محیط پایه ای سیستم را برقرار کند و سرویس ها و منابع سیستم را راه اندازی، نظارت و مدیریت کند . اما نحوه ی پیاده سازی و محدوده ی مسئولیت ها ی systemd بسیار گسترده تر و ساختار یافته تر از sysV است. اهداف کلیدی systemd عبارت اند از مدیریت وابستگی محور واحد ها (units)، راه اندازی موازی برای بهبود زمان بوت، مانیتورینگ و بازیافت خودکار سرویس ها، کنترل منابع (با استفاده از cgroups)، و لاگگیری مرکزی (journal).

مفهوم واحدها (Units) و انواع آنها
در سرویس منیجر systemd هر موجودیت مدیریتی یک Unit نامیده می شود. Unit ها با پسوند هایی مشخص می شوند که نوع شان را تعیین می کند. مهم ترین انواع Unit عبارت اند از :
– .service – سرویس / دیمن (معادل اسکریپت های init).
– .socket – سوکت فعال سازی (در واقع مفهومی است که در این روش فعالسازی فقط در صورتی که تقاضا برای یک سرویس وجود داشته باشد آن سرویس فعال شود).
– .target – تارگت ( می توان معادل runlevel در نظر گرفت ).
– .mount – نقطه ی مونت فایل سیستم. (وظیفه مونت دستگاه های فایل سیستم توسط systemd در زمان راه اندازی سیستم و یا در زمان نیاز).
– .automount – مونت خودکار (نصب و مونت خودکار فایل سیستم جدید در زمان اتصال یا نیاز کاربر از طریق فعال کردن .mount که وظیفه نصب واقعی فایل سیستم را دارد .).
– .timer – تایمر جایگزین cron.
– .path – فعال سازی بر اساس تغییرات مسیر / فایل (کار اصلی این واحد نظارت بر مسیر ها و واکنش به تغییرات فایل یا مسیر است).
– slice / scope – مدیریت منابع و گروه بندی cgroups.
هر Unit با یک فایل متنی با یک ساختار مشخص (تقریبا مشابه با فایل سرویس در sys V) تنظیم می شود که حداقل شامل بخش های [unit] , [service] , و یا [install] است و این Unit ها می توانند وابستگی ها، ترتیب اجرایی و رفتار بازیابی را به وضوح نمایش دهند .
ساختار و سینتکس فایل های Unit و سرویس ها در systemd
در systemd هر سرویس، سوکت، تارگت یا منبع سیستمی توسط یک Unit تعریف می شود.و هر Unit یک فایل متنی با قالب INI دارد که شامل چند بخش مشخص است. مهم ترین آن ها [Unit], [Service] و [Install] هستند.
مسیر های فایل های واحد (Unit files)
فایل های unit به طور معمول به شکل ساختار سلسله مراتبی به ترتیب اولویت و نوع ساختار Unit در یکی از مسیر های زیر ذخیره می شود :
– در بالا ترین اولویت فایل های unit تعریف شده توسط کاربر و unit های کاستومایز شده : /etc/systemd/system/
– سپس در اولویت دوم unit های داینامیک و runtime (واحد های زمان اجرا) در مسیر : /run/systemd/system/
– و در نهایت واحد (unit) های ایجاد شده توسط پکیج های نصب شده (مثل unit های مربوط به sshd ، httpd و nginx) : /usr/lib/systemd/system/
systemd هنگام راه اندازی، تمام Unit های موجود در این مسیر ها را می خواند و گراف وابستگی ها را بر اساس اطلاعات موجود در هر فایل می سازد.
در صورت تغییر یا ساخت هر فایل unit ، باید یک بار دستور systemctl daemon-reload را اجرا کرد تا systemd بتواند فایل های unit جدید و یا تغییر یافته را مجدد ریلود و بارگذاری کند .
ساختار فایل های unit
– برای درک بهتر منطق کاری unit ها در systemd ، اسکریپت زیر نمونه ای از یک سرویس ساده را نشان می دهد:
[Unit] Description= Example Service After=network.target Requires=network.target [Service] Type=simple ExecStart=/usr/bin/myservice Restart=on-failure [Install] WantedBy=multi-user.target
توضیح ساختار :
[unit] : این قسمت نشان دهنده شروع بخش اطلاعات عمومی unit و وابستگی های واحد است .
در بخش Description توضیحاتی در باره ی سرویس گفته می شود .
در بخش هایی مانند After یا Before تعیین ترتیب اجرا سرویس را مشخص می کنیم . و در قسمت Requires وابستگی های سخت سرویس خود را مشخص می کنیم (وابستگی هایی که اگر فعال نشود سرویس ما به مشکل می خورد . (برای مثال سرویس network برای کار با nginx))
[Service] : تعریف نحوه اجرای سرویس در این قسمت انجام می شود .
در این قسمت مواردی مانند مشخصه های سرویس مانند Type ، User ، Group نیز مشخص می شود .
و همچنین دستور اصلی اجرا ی سرویس(ExecStart) ، دستور اصلی برای ریستارت یا ریلود (ExecReload برای ریلود و Restart برای ریستارت) نیز مشخص می شود .
نکته : (در این قسمت همانطور که احتمالا متوجه شده اید دستور ExecStop قرار نگرفته است . این مورد به این دلیل است که در سرویس های ساده که عموما child process ندارند و می توان آن ها را با سیگنال kill عادی نیز متوقف کرد ، نیاز به مشخص کردن دستور ExecStop ندارند و systemd به طور خودکار این مورد را تشخیص می دهد و زمان اجرای دستور systemctl stop myservice.service خودش به طور خودکار سیگنال kill را برای این process ارسال می کند ).
[Install] : این قسمت نیز مشخص کننده ی این است که این سرویس در هنگام بوت در کدام تارگت ها می تواند فعال شود .(برای مثال همین سرویس به دلیل وابستگی به شبکه نمی تواند در تارگت rescue فعال شود چون در این تارگت سرویس network فعال نیست ).
مدیریت وابستگی ها در systemd
همانطور که در بالا اشاره شد سرویس منیجر systemd با ساختن یک dependency graph (نمودار وابستگی سرویس ها ; به این معنی که چه سرویسی باید قبل از سرویس دیگر یا بعد از آن شروع به کار کند و یا به صورت موازی کار کنند .) و تحلیل =Requires=, Wants=, After=, Before و سایر گزینه ها تصمیم می گیرد که کدام Unit ها باید قبل یا بعد از دیگری اجرا شوند. بر خلاف SysV که اجرای ترتیبی بر اساس نام فایل و شماره بود، systemd می تواند Unit هایی را که مستقل اند هم زمان (parallel) اجرا کند و فقط هنگامی ترتیب دهی نماید که وابستگی صریح وجود داشته باشد؛ این باعث کاهش قابل توجه زمان بوت می شود.
انواع Type سرویس ها
سرویس ها در systemd انواع مختلفی دارند که در فایل unit با مشخصه ی Type= شناخته می شوند . در واقع نوع سرویس (Type) ، رفتار process اصلی سرویس رو در هنگام راه اندازی تعیین می کنه (مثلا آیا یک process همان لحظه اجرا و تمام می شود یا بعد از احرا خودش را fork می کند ؟) .
انواع مختلف Type ها به شرح زیر است :
– simple = در این نوع وقتی systemd سرویس رو با ExecStart اجرا میکنه، همان پردازش ایجاد شده، پردازش اصلی سرویس محسوب می شود. در واقع یعنی systemd فرض می کند سرویس بلافاصله بعد از اجرا «در حال اجرا» است، بدون این که منتظر چیزی بماند .
این نوع بیشتر مناسب برنامه ها و کد هایی است که باید در حال اجرا باقی بمانند و فرایند های پیچیده تر مانند process forking ندارد . (مثل یک ربات تلگرامی یا یک اپ nodejs که از websocket استفاده می کند .)
– forking = درباره ی این نوع اول باید با مفهوم fork کردن بیشتر آشنا بشید :
در لینوکس (و کل خانواده یونیکس)، وقتی که برنامه اجرا می شود، خودش می تواند یک process جدید ایجاد کند (process اول را به عنوان فرآیند پدر (parent) و process ایجاد شده را فرآند فرزند (child) می نامند). در فرایند forking ، سیستم یک کپی از فرآیند فعلی که در حال اجرا است می سازد و این دو فرآیند (parent و child) همزمان ادامه پیدا می کنند (اما باتوجه به اینکه دو پردازش متفاوت هستند ، مقادیر برگشتی و PID متفاوتی دارند).
این کار در بسیاری از daemon های قدیمی مثل sshd ، mysql ،apache و … ، بعد از اجرای دیمن انجام می شود و دلیل اصلی این کار این است که فرایند اصلی در ترمینال ایجاد شده و با بسته شدن ترمینال از بین می رود ، در نتیجه دیمن یک کپی از خودش را در بکگراند سیستم fork می کند و سپس process اصلی را exit می کند . به این شکل در صورت بسته شدن ترمینال هم process در بکگراند در حال اجرا است .
این کار با تابعی به نام fork() در برنامه انجام می شود .
و حالا اینجاست که مفهوم نوع forking را متوجه می شویم : در واقع process پدر و فرزند دو PID متفاوت دارند و برای همین وقتی نوع forking را برای سرویس در نظر می گیریم ، systemd می فهمد که سرویس در واقع یک دیمن سنتی است که عمل fork را انجام می دهد . در این صورت بعد از اجرا منتظر می ماند تا process پدر تمام شود و سپس با مشخصه ی PIDFile= در فایل unit می تواند child را بشناسد .
– oneshot = این نوع برای اسکریپت ها یا دستوراتی به کار می رود که فقط یک بار اجار می شوند و بعد تمام می شوند . systemd بعد از پایان اجرای دستور ، سرویس را تمام شده در نظر می گیرد . (مثل یک سرویس اتوماسیون بکاپ گیری که فقط می خواهید قبل از بروزرسانی ها به صورت دستی بکاپ بگیرید . در این صورت قبل از هر تغییر در پروژه به راحتی می توانید با دستور systemctl start backup.service این بکاپ را ایجاد کنید .)
– notify = در این حالت برنامه باید خدش وقتی آماده ی سرویس دهی شد با استفاده از یک تابع مخصوص مربوط به systemd در برنامه اطلاع رسانی کند که آماده ی کار است .این نوع بیشتر توسط برنامه های پیجیده تری که بعد از اجرای اولیه نیاز به کمی زمان برای آماده شدن دارند استفاده می شود .
– dbus = سیستم D-Bus یک سیستم پیام رسانی بین process ها در لینوکس است . در واقع یعنی یک کانال ارتباطی بین برنامه ها است تا بدون این که مستقیما از فایل یا سوکت استفاده کنند ، بتوانند پیام رد و بدل کنند .
Targets — معادل مدرن Runlevels
سرویس منیجر systemd به جای مفهوم عددی runlevel از target استفاده می کند که مجموعه ای از Unit ها را مدیریت و اجرا یا stop می کنند.
برای راحتی کار در هر دو سیستم sysV و systemd و عادت کاربران به استفاده از دستورات init در اوایل معرفی systemd ، دستور های init به معادل های خود در systemd لینک شد تا کاربران استفاده راحت تری داشته باشند . برخی نمونه های موجود در زیر آمده است :
– Runlevel 0 – poweroff.target
– Runlevel 1 – rescue.target
– Runlevel 3 – multi-user.target
– Runlevel 5 – graphical.target
– Runlevel 6 – reboot.target
که می توان دقیقا به شکل همان دستور های قبلی init به تارگت مد نظر تغییر کرد (برای مثال دستور init 5 برای رفتن به مود گرافیکی) .
اما در حالت کلی systemd کامند های مخصوص به خود را دارد و کامند های sysV همانطور که بالاتر هم اشاره شد درواقع لینک شده (شورتکات) به کامند های اصلی systemd هستند .
برای مثال در systemd برای تغییر تارگت می توانیم از دستور زیر استفاده کنیم :
systemctl isolate <target name>
مثال (برای رفتن به مود مولتی یوزر) :
systemctl isolate multi-user.target
مدیریت سرویس ها با systemctl و دستورات مرتبط
برای انجام کار با سرویس ها و تارگت ها و در کل هر کاری که مربوط به مدیریت سرویس ها در سرویس منیجر باشد در سیستم هایی که از systemd استفاده می کنند ، عمدتا از دستور systemctl و آپشن های متفاوتی که برای انجام کار های مختلف دارد استفاده می شود . در واقع systemctl ابزار اصلی مدیریت سرویس ها و targets در systemd است. این ابزار جایگزین مجموعه دستورات قدیمی SysVinit شده و توانایی کنترل کامل lifecycle سرویس ها، وضعیت آن ها، وابستگی ها و رفتار بوت را دارد.
کنترل اجرای سرویس ها
سرویس مشخص را فوراً اجرا میکند. اگر سرویس فعال باشد، تغییری ایجاد نمی شود :
systemctl start myservice.service
سرویس مشخص را متوقف می کند :
systemctl stop myservice.service
سرویس را ریستارت می کند :
systemctl restart myservice.service
به سرویس سیگنال reload می فرستد تا پیکربندی خودش را مجددا بارگذاری کند، بدون توقف کامل. تنها سرویس هایی که از ExecReload پشتیبانی می کنند، پاسخ می دهند :
systemctl reload myservice.service
فعال و غیرفعال کردن سرویس ها در بوت
سرویس در زمان بوت سیستم فعال می شود :
systemctl enable myservice.service
سرویس در زمان بوت اجرا نمی شود :
systemctl disable myservice.service
بررسی میکند که سرویس برای بوت فعال است یا خیر :
systemctl is-enabled myservice.service
سرویس کاملا غیرقابل اجرا می شود، حتی اگر دستی اجرا شود :
systemctl mask myservice.service
برعکس mask، سرویس دوباره قابل اجرا می شود :
systemctl unmask myservice.service
بررسی وضعیت سرویس ها
نمایش وضعیت فعلی سرویس، PID اصلی، زمان فعال شدن، و آخرین لاگ های journal مربوط به آن :
systemctl status myservice.service
بررسی می کند که سرویس فعال است یا خیر (active / inactive / failed) :
systemctl is-active myservice.service
نمایش تمام Property های سرویس، مثل ExecStart, Restart, MainPID, ActiveState :
systemctl show myservice.service
لیست تمام سرویس های فعال به همراه وضعیت آن ها :
systemctl list-units --type=service
وابستگی ها و گراف بوت
نمایش سلسله مراتب وابستگی ها برای target یا سرویس مشخص :
systemctl list-dependencies mytarget.target
نمایش سرویس هایی که به سرویس مشخص وابسته هستند :
systemctl list-dependencies --reverse myservice.service
نمایش سرویس هایی که بیشترین زمان را در بوت مصرف کرده اند :
systemctl analyze blame
نمایش زنجیره ی بحرانی اجرای سرویس ها و target ها در بوت. نشان می دهد کدام سرویس ها تاخیر ایجاد می کنند :
systemctl analyze critical-chain
تغییر target یا runlevel
برای نمایش تارگت دیفالت سیستم :
systemctl get-default
برای تغییر تارگت پیش فرض به تارگت دیگر :
systemctl set-default <target name>
و برای تغییر تارگت فعلی :
systemctl isolate <target name>
مدیریت فایل های unit و reload systemd :
بعد از تغییر یا ساخت فایل های unit، systemd با این دستور فایل ها را دوباره بارگذاری می کند تا تغییرات اعمال شود :
systemctl daemon-reload
ایجاد یا ویرایش override برای یک سرویس بدون تغییر فایل اصلی :
systemctl edit myservice.service
نمایش محتوای کامل فایل unit :
systemctl cat myservice.service
مدیریت لاگ ها با journalctl
سرویس منیجر systemd شامل سرویس systemd-journald است که وظیفه جمع آوری، ذخیره سازی و مدیریت لاگ های سیستم و سرویس ها را بر عهده دارد. برخلاف سیستم های سنتی مانند syslog، که لاگ ها را به صورت متن ساده ذخیره می کنند، systemd-journald لاگ ها را به شکل ساختار یافته و باینری نگه می دارد. این ویژگی باعث می شود که بتوان با فیلتر های پیچیده و گزینه های جستجوی دقیق، به راحتی اطلاعات مورد نیاز را استخراج کرد.
نمایش لاگ های سرویس ها
برای مشاهده لاگ های یک سرویس مشخص از گزینه -u استفاده می شود:
journalctl -u myservice.service
نکته : با افزودن آپشن های –since و –until می توان بازه زمانی دلخواه را انتخاب کرد :
journalctl -u myservice.service --since "2025-10-10 08:00" --until "2025-10-10 12:00"
نمایش لاگ های مربوط به بوت فعلی
نمایش لاگ هایی که از شروع بوت فعلی تولید شده اند :
journalctl -b
نکته : با افزودن -1 میتوان لاگهای بوت قبلی را مشاهده کرد:
journalctl -b -1
آپشن -x توضیحات بیشتری درباره لاگ ها اضافه می کند . و آپشن -e نمایش لاگ ها را از انتهای فایل شروع می کند. :
journalctl -xe
برای مشاهده لاگ های چند بوت اخیر می توان از اعداد منفی یا گزینه –list-boots استفاده کرد :
journalctl --list-boots
دنبال کردن زنده لاگ ها
نمایش real time لاگ ها :
journalctl -f
نکته : می توان آن را با فیلتر سرویس ترکیب کرد :
journalctl -u myservice.service -f
نتیجه گیری
در یک جمع بندی کوتاه، میتوان گفت که هر دو سرویس منیجر SysVinit و systemd نقش یکسانی در مدیریت فرآیند های بوت و سرویس ها دارند، اما در فلسفه و کارکرد تفاوت بنیادین دارند.
SysVinit سیستمی ساده، پایدار و قابل پیش بینی است که برای سرور های سبک، سیستم های توکار (Embedded) و محیط هایی با نیاز به حداقل وابستگی مناسب تر است. در عوض، systemd با ساختار ماژولار، راه اندازی موازی، مدیریت وابستگی ها و پشتیبانی از cgroups و journald، برای سیستم های مدرن، سرور ها، و محیط های ابری طراحی شده است.
| ویژگی | SysV init | Systemd |
|---|---|---|
| ساختار | مبتنی بر اسکریپت های شل و runlevels | مبتنی بر واحد های declaratory |
| راه اندازی سرویس | سریال (یکی پس از دیگری) | موازی (همزمان) |
| مدیریت وابستگی | دستی و محدود | خودکار و پیشرفته (Requires, Wants) |
| نظارت بر سرویس | بدون نظارت خودکار | نظارت و restart خودکار |
| لاگینگ | وابسته به syslog | یکپارچه با journald |
| سرعت بوت | کند تر | سریع تر |
| پیچیدگی | ساده و قابل فهم | پیچیده اما قدرتمند |
| سازگاری | سیستم های قدیمی | توزیع های مدرن مانند Ubuntu, Fedora |
| ابزار ها | service, chkconfig | systemctl, journalctl |





