در April سال ۲۰۱۲ تشکل دبیان قبول کرد که به طور رسمی از systemd استفاده نماید. اولین Systemd-on-fedoraمرحله استفاده آن، فقط از دایمون systemd-logind در پاییز ۲۰۱۳ بود تا اینکه بالاخره در April سال ۲۰۱۴ به طور رسمی SysV جای خود بر روی مخزن unstable دبیان به systemd داد و قول دبیان مبنی بر این است که نسخه بعدی آن با کد jessie به طور کامل با systemd سازگار است.
در بالا ذکر شد مهاجرت به صورت فرآیندی(مرحلهای) صورت گرفته است. اما چرا بعضی از توزیعها منجمله دبیان زمانی که میخواهند یک مهاجرت سنگین در سطح low level انجام دهند احتیاط میکنند؟ بگذارید گزاره اصلی را پیشرفت systemd بگیریم.
systemd بر خلاف سیستمهای boot دیگر همانند Upstart یا SysV به شدت بر روی کل سیستم تأثیر میگذارد از جمله نقاطی که میتوان نام برد، کرنل، udev، D-Bus، ارتباطات شبکه و علی الخصوص اینکه بدلیل اینکه systemd یک سیستم بوت میباشد باید کل process های سیستم را مدیریت کند.
اگر به تمامی تأثیرات بالا به صورت دوطرفه نگاه کنیم، خواهیم دید که یک توزیع نه تنها در یک زمان بر روی کلی از ساختارهای اصلی خود تأثیری میگذارد که نتیجه آن مشخص نیست بلکه ممکن است دچار Bug نیز نماید. پس بهترین راه مهاجرت فرآیندی است. این نوع مهاجرت دو حسن دارد:
-
خود سیستم اصلی که systemd باشد رشد میکند.
-
geek ها بر روی آن کار میکنند و مشکلات آن را طی زمان گزارش میکنند و این روند لطمهای به توزیعهای پایدار همانند دبیان نمیزند.
اما مهاجرت غیر فرآیندی نیز خود حسنهایی دارد که از آنجمله میتوان به موجب رشد سریع خود نرمافزار اصلی اشاره کرد.
برای بررسی systemd بهتر است بعضی از مفاهیم سیستم بوت را بررسی نماییم تا مشکلات، طرحوارهها، امروز این نرمافزارها و آینده آن بررسی شود تا نسبت به طراحی systemd دیدی از بالا داشته باشیم.
برای بررسی یک سیستم بوت به توضیح اجمالی یکی از آنها نیاز است. بین ۳ سیستم بوت معروف SysV، OpenRC و Upstart با کالبد شکافی بعضی از مفاهیمی که جلوتر برای systemd نیاز است در SysV میپردازیم. مخصوصاً اینکه systemd کدی را با SysV به اشتراک میگذارد.
در تمامی یونیکسها قسمت سیستم بوت فایل اجرایی با نام init دارد که کرنل PID شماره ۱ را برای آن رزرو میکند. کار اصلی سیستم بوت، مدیریت پردازشها میباشد. اگر قرار بود که کرنل به مدیریت پردازشها هم برسد کار کرنل واقعاً سنگین میشد.
همانطور که توضیح داده شد، دستور init فایل اجرایی سیستم بوت در تمام سیستمها میباشد و دارای چند قاعده میباشد:
۱. PID آن ۱ میباشد.
۲. در هر سیستم که سیستم بوت آن فرق میکند پارامترهای جداگانهای میگیرد.
۳. اولین پردازشی میباشد که بعد از کرنل اجرا میشود:
1 2 3 |
root@debian:/home/mohsen# ps -ef |head -n 2 UID PID PPID C STIME TTY TIME CMD root 1 0 0 Jun12 ? 00:00:02 /sbin/init |
۴. همانطور که از دستور بالا پیداست این پردازش دارای هیچ پردازش والدی نمیباشد.(0 == PPID)
نکته: قواعد زیر مربوط به گنو/لینوکس میباشند و خاص SysV میباشند:
۵. فرآیند سیستم بعد از کرنل به دست سیستم بوت میافتد. به گونهای میتوان گفت همه چیز را منجمله runlevel پیشفرض را میتوان در آن تعیین کرد.
۶. SysV دارای فایلی با نام etc/inittab/ میباشد که دارای قواعد خویش است و بهتر است به صورت گذرا بر روی آن بحث کنیم:
-
تمام خطوط دارای نحو (syntax) زیر میباشند:
-
در هر خط جداکننده فیلدها ”:” میباشد. به مثال زیر دقت کنید:
-
نکته اصلی در inittab همان action ها هستند که خواندن آنها خالی از لطف نیست یا بهتر است بگوییم الزامیست برای کار کردن با هر گونه boot process که بخواهیم دستکاری کنیم.
1 |
id:runlevels:action:process |
1 |
zd:25:respawn:/opt/zebedee/bin/zebedee -f /opt/zebedee/lib/zebedee/config.zbd |
یک ID با نام zd تعریف کردیم و به init گفتهایم که فایل /opt/zebedee/bin/zebedee/ را با پارامتر مربوطه در حالت respawn و در سطوح اجرایی ۲ و ۵ اجرا نماید.
نکته: تعریف ID برای هر خط الزام دارد و باید منحصر به فرد باشد.
۷. گنو/لینوکس یک یونیکس SystemV میباشد و طبیعتاً سطوح اجرایی دارد. قصد باز کردن اینکه یک سطح اجرایی چیست را نداریم بلکه در فرآیند یک بوت پراسس چند عامل زیر مد نظر میباشد که خیلی مهم هستند:
-
سرویسهای درون یک سطح اجرایی نسبت به یکدیگر دارای اولویت میباشند. فرض کنید سرویس x به سرویس y وابستگی دارد و تا سرویس y بالا نیاید سرویس x نیز اجرا نمیشود. به این موضوع dependency loop گفته میشود که بدین منظور SysV در دایرکتوری /etc/init.d/ سه فایل با نامهای depend.boot ، .depend.start. و depend.stop. وجود دارند که چگونگی dependency سرویسهای SysV را مشخص میکنند.
-
مشکل سرعت بوت فقط به یک عامل بستگی ندارد و چندین عامل را در بردارد که خالی از لطف نیست که اصلیترین عوامل آن مطرح گردند:
-
سریالی اجرا شدن سرویسها.
-
هر کدام از دایمونها به طور جداگانه سوکت خود را دارند که این سرعت را پایین میآورد.
-
در اسکریپت اجرایی هر سرویس ممکن است کلی grep, sed،awk و یا کلی دستوراتی اینچنینی اجرا شوند که خود این امر به صورت تصاعدی سرعت را کاهش میدهد.
-
علاوه بر دستورات بالا برای اجرای فایل اسکریپت حاضر در /etc/init.d/ به ازای هر اسکریپت باید یک شل اجرا گردد که کلی راندمان منفی دارد.
-
پهنای IO،CPU و غیره نیز اگر به صورت جداگانه باشند سرعت را پایین میآورند.
۸. بدیهی است مدیریت پردازشها در گنو/لینوکس به عهده boot process میباشد. اما مسأله اصلی که برای ما مهم است حمله PID ها در یک زمان به سیستمعامل میباشد.
۹. انتخاب سطح اجرایی با boot process میباشد.
systemd:
unit چیست؟
systemd به هفت unit تقیسم میشود. ترکیب سرویس مورد نظر در /etc/init.d/ با نام unit یک نام ایجاد میکند که این نام مشخصهای است برای نوع unit و دیگری نام سرویس، به نحوه نامگذاری زیر دقت نمایید:
1 |
cron.service |
در ابتدا نام سرویس و سپس با جداکننده ”.” نام unit مورد نظر گذاشته میشود. هفت unit مورد نظر در زیر لیست شدهاند که برای هرکدام توضیح و مثال میاوریم:
-
service
-
socket
-
device
-
mount
-
automount
-
target
-
snapshot
۱. service : این unit که مشهودترین unit از بین هفت سرویس نام برده شده میباشد، مسئول start، stop، restart و reload سرویس مذکور میباشد. به این دلیل که هر فایل شلی کلی راندمان منفی ایجاد میکند، systemd قادر نخواهد بود فایلهای /etc/init.d/ را بخواند و تنها از درون آنها هدر های LSB را میخواند(هدر LSB به صورت comment و اول فایل است.). اگر از SysV به یاد داشته باشید هر اسکریپت درون etc/init.d/ در ابتدای فایل به صورت زیر از هدر های LSB استفاده میکرد:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# Provides: cups # Required-Start: $syslog $remote_fs # Required-Stop: $syslog $remote_fs # Should-Start: $network avahi-daemon slapd nslcd # Should-Stop: $network # X-Start-Before: samba # X-Stop-After: samba # Default-Start: 2 3 4 5 # Default-Stop: 1 # Short-Description: CUPS Printing spooler and server # Description: Manage the CUPS Printing spooler and server; # make it's web interface accessible on http://localhost:631/ ### END INIT INFO |
خطوط بالا از اسکریپت cups برداشته شده است.
به نحوه نامگذاری زیر دقت کنید:
1 |
acpid.service |
در این نام سرویس acpid را ملاحظه میکنیم.
۲. socket : در گذشته خاطر نشان شدیم اگر هر برنامه، دایمون و غیره به تنهایی بخواهد یک socket داشته باشد از سرعت boot process کاسته خواهد شد. راه حلی که systemd ارایه کرده است مجتمع کردن انواع connection ها حتی fifo میباشد. از اینرو این unit معرفی شده است. به نامگذاری زیر دقت نمایید:
1 |
dbus.socket |
۳. device : در گذشته بیان شد که هر چیزی که به سطح بالاتر بیاید به سرعت نیز کمک میکند(البته نه هر چیزی). این device ، unit مربوطه را در Linux Device Tree قرار میدهد. اگر یک devive به صورت یک rule در udev مارک شده باشد، systemd آن را به صورت یک unit در خواهد آورد.
۴. mount : اگر بخواهیم به صورت خیلی خیلی خلاصه راجعبه این unit بگوییم، میتوان گفت هر فایل mount مترادف هر خط etc/fstab/ میباشد. این unit از etc/fstab/ به صورت یک فایل پیکربندی سنتی نیز استفاده مینماید.
۵. automount : این unit یک automount point به systemd اضافه میکند. هر automount باید با یک unit نوشته شده با mount مطابقت کند.
۶. target : این نوع unit برای گروهبندی منطقی unitها استفاده میشود تا دیگر خود unitها به یکدیگر ارجاع ندهند(برعکس Upstart).
۷. snapshot : همانند target ها snapshot ها نیز به خودی خود کاری انجام نمیدهند. آنها به یکدیگر ارجاع داده میشوند. آنها میتوانند برای save/rollback تمام سرویسها و unit ها به کار گرفته شوند. آنها به دو منظور اصلی: ورود موقت به یک وضعیت خاص همانند شل اورژانسی، قطع سرویس جاری و برای برگشت به وضعیت قبل میباشد و بهتر suspend و shutdown شدن سیستم متولد شدند.
در شماره بعد به مفاهیم بیشتری در مورد systemd و نحوه عملکرد آن با دستورات و پیکربندی unit فایلها خواهیم پرداخت.