زمانی که رایانه را راهاندازی میکنید، پیامهای زیادی که در کنسول به شما نمایش داده میشوند نشاندهنده عملیات خودکار راهاندازی و پیکربندی سیستم هستند. شاید بعضی وقتها بخواهید تغییری در این مرحله ایجاد کنید، که به معنای درک اولیه صحیح از آن است. هدف این قسمت نیز همین است.
9.1.1. سیستم راهانداز systemd
“init حقیقی” توسط systemd ارائه شده است که این قسمت به بررسی آن میپردازد.
... فرآیندهای بسیاری را اجرا میکند، که مسئول راهاندازی سیستم هستند: صفحهکلید، درایورها، فایلسیستمها، شبکه، سرویسها. این عملیات را هنگامی که کل سیستم را تحت نظر دارد اجرا میکند و به بررسی پیشنیازهای هر یک میپردازد. هر جزء توسط یک “unit file” توضیح داده میشود (بعضی وقتها بیشتر)؛ شیوه نگارش آن بر اساس قالب شناختهشده “*.ini files“ است، به همراه جفت مقادیر key = value
که در بین سرآیندهای [section]
گروهبندی شدهاند. این فایلها در مسیر /lib/systemd/system/
و /etc/systemd/system/
ذخیرهسازی شدهاند؛ آنها به شیوههای گوناگونی وجود دارند که در اینجا به بررسی “سرویسها” و “اهداف” میپردازیم.
یک “فایل سرویس” از systemd به یک فرآیند قابل مدیریت توسط آن را توضیح میدهد. تقریبا همان اطلاعات اسکریپتهای قدیمی init را دارا هستند اما به شیوهای نوین و مختصر بیان شده است. systemd عمده فعالیتهای تکراری را بر عهده میگیرد (آغاز و پایان یک فرآیند، بررسی وضعیت آن، گزارشگیری، بررسی مجوزها و از این قبیل) و فایل سرویس تنها لازم دارد موارد خاص آن فرآیند را بیان کند. برای نمونه، در اینجا نمونهای از فایل سرویس مربوط به SSH را میبینیم:
[Unit]
Description=OpenBSD Secure Shell server
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run
[Service]
EnvironmentFile=-/etc/default/ssh
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target
Alias=sshd.service
همانطور که مشاهده میکنید، کد بسیار کمی در آن وجود دارد، تنها تعریفهای مورد نیاز. systemd مواردی از قبیل نمایش گزارشهای پیشرفت، بررسی وضعیت فرآیندها و حتی اجرای مجددشان هر زمان لازم باشد را انجام میدهد.
یک “فایل هدف” از systemd به تشریح وضعیت یک سیستم میپردازد، که در آن مجموعهای از سرویسها اعمال میشوند. این فایل میتواند به عنوان معادل قدیمی runlevel فرض شود. یکی از اهداف local-fs.target
است؛ زمانی که محقق گردد، باقی سیستم میتوانند تصور کنند که تمام فایلسیستمهای محلی متصل شده و قابل دسترس هستند. سایر اهداف شامل network-online.target
و sound.target
میشوند. وابستگیهای یک هدف میتوانند درون فایل آن نوشته شوند (در خط Requires=
) یا از یک پیوند نمادین به یک فایل سرویس در دایرکتوری /lib/systemd/system/targetname.target.wants/
استفاده شوند. برای نمونه، /etc/systemd/system/printer.target.wants/
شامل پیوندی به /lib/systemd/system/cups.service
است؛ systemd اطمینان مییابد که برای دسترسی به printer.target
ابتدا CUPS باید اجرا گردد.
از آنجا که فایلهای واحد بر خلاف اسکریپتها یا برنامهها جنبه بیانی دارند، به طور مستقیم قابل اجرا نیستند و تنها توسط systemd تفسیر میگردند؛ برخی ابزارهای جانبی این امکان را به مدیرسیستم میدهند که به صورت تعاملی با systemd برخورد کرده و هر یک از اجزای آن را مدیریت کنند.
اولین ابزار در این زمینه systemctl
نام دارد. زمانی که بدون هیچ پارامتری اجرا گردد، به فهرست کردن تمام فایلهای واحد شناختهشده برای systemd میپردازد (به جز آنهایی که غیرفعال شدهاند) به همراه وضعیت هر کدام. systemctl status
دید مناسبتری از سرویسها را ارائه میدهد، به همراه فرآیندهای مربوط به هر کدام. اگر نام یک سرویس نیز داده شود (مانند systemctl status ntp.service
) جزئیات بیشتری نیز نمایش داده میشود به همراه آخرین خطوط گزارش مرتبط با آن (که بعدا به آن میرسیم).
شروع یک سرویس به صورت دستی به سادگی اجرای دستور systemctl start servicename.service
است. همانطور که حدس زدید، توقف سرویس با استفاده از systemctl stop servicename.service
صورت میگیرد؛ سایر دستورات زیر-مجموعه عبارتند از reload
و restart
.
به منظور اطلاع از فعالبودن یک سرویس (خواه در زمان راهاندازی سیستم اجرا شده باشد یا خیر) از دستور systemctl enable servicename.service
استفاده کنید (یا disable
). is-enabled
برای بررسی وضعیت سرویس بکار میرود.
یک ویژگی جالب از systemd افزودن یک جزء به نام journald
است. به عنوان یک مکمل برای سیستمهای گزارشگیری قدیمیتر مانند syslogd
به حساب میآید که ویژگیهای جالبی مانند افزودن یک پیوند رسمی بین سرویس و پیامهایی که تولید میکند یا قابلیت دریافت پیامهای خطای تولید شده توسط ترتیب اولیه آنها را شامل میشود. پیامها در ادامه میتوانند نمایش داده شوند، با اندکی کمک از دستور journalctl
. بدون هیچ پارامتری، به تشریخ تمام پیامهای لاگ که از راهاندازی سیستم دریافت کرده است میپردازد؛ البته به این شکل کمتر استفاده میشود. در اکثر موارد، به همراه شناسه یک سرویس بکار میرود:
#
journalctl -u ssh.service
-- Logs begin at Tue 2015-03-31 10:08:49 CEST, end at Tue 2015-03-31 17:06:02 CEST. --
Mar 31 10:08:55 mirtuel sshd[430]: Server listening on 0.0.0.0 port 22.
Mar 31 10:08:55 mirtuel sshd[430]: Server listening on :: port 22.
Mar 31 10:09:00 mirtuel sshd[430]: Received SIGHUP; restarting.
Mar 31 10:09:00 mirtuel sshd[430]: Server listening on 0.0.0.0 port 22.
Mar 31 10:09:00 mirtuel sshd[430]: Server listening on :: port 22.
Mar 31 10:09:32 mirtuel sshd[1151]: Accepted password for roland from 192.168.1.129 port 53394 ssh2
Mar 31 10:09:32 mirtuel sshd[1151]: pam_unix(sshd:session): session opened for user roland by (uid=0)
گزینه جالب دیگر در خط-فرمان -f
است که به journalctl
میگوید به نمایش پیامهای جدید اضافهشده به انتهای فایل بپردازد (مانند عملکردی که tail -f file
دارد).
اگر سرویس عملکرد مورد نظر را نداشته باشد، اولین مرحله عیبیابی این است که بدانیم آیا سرویس اجرا شده است یا خیر با استفاده از دستور systemctl status
؛ اگر اجرا نشده بود و پیامهای دستور اول به عیبیابی مشکل کمکی نکرد، به بررسی گزارشهای تهیه شده توسط journald مرتبط با آن سرویس بپردازید. برای نمونه، تصور کنید که سرویس SSH کار نمیکند:
#
systemctl status ssh.service
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled)
Active: failed (Result: start-limit) since Tue 2015-03-31 17:30:36 CEST; 1s ago
Process: 1023 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
Process: 1188 ExecStart=/usr/sbin/sshd -D $SSHD_OPTS (code=exited, status=255)
Main PID: 1188 (code=exited, status=255)
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service start request repeated too quickly, refusing to start.
Mar 31 17:30:36 mirtuel systemd[1]: Failed to start OpenBSD Secure Shell server.
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
#
journalctl -u ssh.service
-- Logs begin at Tue 2015-03-31 17:29:27 CEST, end at Tue 2015-03-31 17:30:36 CEST. --
Mar 31 17:29:27 mirtuel sshd[424]: Server listening on 0.0.0.0 port 22.
Mar 31 17:29:27 mirtuel sshd[424]: Server listening on :: port 22.
Mar 31 17:29:29 mirtuel sshd[424]: Received SIGHUP; restarting.
Mar 31 17:29:29 mirtuel sshd[424]: Server listening on 0.0.0.0 port 22.
Mar 31 17:29:29 mirtuel sshd[424]: Server listening on :: port 22.
Mar 31 17:30:10 mirtuel sshd[1147]: Accepted password for roland from 192.168.1.129 port 38742 ssh2
Mar 31 17:30:10 mirtuel sshd[1147]: pam_unix(sshd:session): session opened for user roland by (uid=0)
Mar 31 17:30:35 mirtuel sshd[1180]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:35 mirtuel sshd[1182]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:35 mirtuel sshd[1184]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel sshd[1186]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel sshd[1188]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service start request repeated too quickly, refusing to start.
Mar 31 17:30:36 mirtuel systemd[1]: Failed to start OpenBSD Secure Shell server.
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
#
vi /etc/ssh/sshd_config
#
systemctl start ssh.service
#
systemctl status ssh.service
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled)
Active: active (running) since Tue 2015-03-31 17:31:09 CEST; 2s ago
Process: 1023 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
Main PID: 1222 (sshd)
CGroup: /system.slice/ssh.service
└─1222 /usr/sbin/sshd -D
#
پس از بررسی وضعیت سرویس (failed)، به بررسی فایلهای گزارش پرداختیم؛ آنها نشان دادند که یک خطا در فایل پیکربندی وجود دارد. پس از ویرایش فایل پیکربندی و اصلاح خطا، سرویس را راهاندازی مجدد کردیم و دیدیم که به درستی کار میکند.
9.1.2. سیستم راهانداز System V
سیستم راهانداز System V (که به اختصار init مینامیم) چندین فرآیند را اجرا میکند، که دستورالعملهای آن در فایل
/etc/inittab
آمده است. اولین برنامهای که اجرا میشود (که معادل با گام
sysinit است) برابر با
/etc/init.d/rcS
است، اسکریپتی که سایر برنامههای موجود در دایرکتوری
/etc/rcS.d/
را اجرا میکند.
در میان آنها، برنامههای پیدرپی مرتبطی پیدا خواهید کرد:
پیکربندی صفحهکلید کنسول؛
بارگیری درایورها: اکثر ماژولهای کرنل توسط خودش هنگام شناسایی سختافزار بارگیری میشوند؛ درایورهای اضافی به صورت خودکار زمانی که ماژول مربوطه در فایل /etc/modules
قرار گیرد بارگیری میشوند.
بررسی جامعیت فایلسیستمها؛
متصلکردن پارتیشنهای محلی؛
پیکربندی شبکه؛
متصلکردن فایلسیستمهای شبکه یا NFS.
پس از این گام، init
وارد میشود و برنامههای فعالشده در runlevel پیشفرض (که معمولا شماره ۲ است) را آغاز میکند. به اجرای /etc/init.d/rc 2
میپردازد، اسکریپتی که تمام سرویسهای موجود در /etc/rc2.d/
که با حرف “S” شروع میشوند را آغاز میکند. عدد دو رقمی که بعد از نام هر سرویس قرار دارد ترتیب اجرای آنها را مشخص میکند، اما امروزه سیستم راهانداز پیشفرض از insserv
به این منظور استفاده میکند، که تمام مراحل را با توجه به وابستگیهای بین اسکریپتها زمانبندی میکند. هر اسکریپت راهانداز شرایط مربوط به خود جهت اَغاز یا پایان سرویس را توصیف میکند (برای نمونه، اگر باید قبل یا بعد از یک سرویس دیگر آغاز گردد)؛ init
سپس به اجرای آنها با توجه به شرایط موجود میپردازد. بنابراین شمارهگذاری ایستا که در اسکریپتها استفاده میشد دیگر به حساب نمیآید (اما آنها باید نامی که با “S” شروع میشود به همراه عدد دو رقمی و نام حقیقی سرویس را به همراه داشته باشند). در حالت کلی، سرویسهای پایه (مانند گزارشگیری با rsyslog
یا تخصیص پورت با portmap
) در ابتدا آعاز میگردند به همراه سرویسهای استاندارد و رابط گرافیکی (gdm3
).
این سیستم راهانداز مبتنی بر وابستگیها امکان شمارهگذاری مجدد را فراهم میکند، کاری که در حالت دستی دشواریهای فراوانی دارد و امکان خطای انسانی را کاهش میدهد چرا که زمانبندی مختص به پارامترهای مشخص شده میباشد. مزیت دیگر آن این است که سرویسها میتوانند به صورت موازی آغاز شوند زمانی که به یکدیگر وابسته نیستند، که این امر به فرآیند راهاندازی سرعت میبخشد.
... قابلیت شناسایی چندین runlevel را دارد، پس میتواند بین آنها با استفاده از دستور telinit new-level
جابجا شود. بلافاصله، init
به اجرای /etc/init.d/rc
با runlevel جدید میپردازد. این اسکریپت به اجرای سرویسهای مفقود و توقف آنهایی که دیگر مورد نیاز نیستند میپردازد. به این منظور، به محتوای موجود در مسیر /etc/rcX.d
ارجاع میکند (که X نشاندهنده runlevel جدید است). اسکریپتهایی که با “S” شروع میشوند (به معنای “Start”) سرویسهایی هستند که باید آغاز گردند؛ آنهایی که با “K” شروع میشوند (به معنای “Kill”) سرویسهایی هستند که باید متوقف گردند. اسکریپت به اجرای سرویس فعال در runlevel قبلی نمیپردازد.
به صورت پیشفرض، سیستم راهانداز System V در دبیان از چهار runlevel متفاوت استفاده میکند:
سطح ۰ هنگام خاموش شدن رایانه به صورت موقتی استفاده میشود. به همین دلیل شامل بسیاری اسکریپتهای “K” است.
سطح ۱، که به نام حالت تک-کاربره نیز شناخته میشود، مطابق با سیستم در حالت عیبیابی است؛ تنها شامل سرویسهای پایه است و مناسب عملیات عیبیابی است که تعامل با کاربران در آن مد نظر نباشد.
سطح ۲ برای عملکرد نرمال استفاده میشود که شامل سرویسهای شبکه، رابط گرافیکی، ورود کاربر و از این قبیل است.
سطح ۶ که به سطح ۰ مشابه است تنها با این تفاوت که برای حالت راهاندازی مجدد رایانه استفاده میگردد.
سطحهای دیگری نیز وجود دارند، به خصوص ۳ تا ۵. به صورت پیشفرض آنها مانند سطح ۲ عمل میکنند، اما مدیرسیستم میتواند آنها را تغییر دهد (با افزودن یا حذف اسکریپتهایی در دایرکتوری /etc/rcX.d
) تا آنها را برای نیازهای خاص سازگار سازد.
تمام اسکریپتهای موجود در دایرکتوریهای /etc/rcX.d
تنها پیوندهای نمادین هستند - که توسط برنامه update-rc.d
هنگام نصب یک بسته ایجاد میگردند - که به اسکریپتهای اصلی ذخیرهشده در /etc/init.d/
اشاره میکنند. مدیرسیستم میتواند به بهینهسازی سرویسهای موجود در هر runlevel با اجرای دستور update-rc.d
به همراه پارامترهای لازم بپردازد. صفحه راهنمای update-rc.d(1) به تشریح شیوه استفاده از آن پرداخته است. به یاد داشته باشید که حذف پیوندهای نمادین (با پارامتر remove
) روش خوبی برای غیرفعالکردن یک سرویس نیست. در عوض باید طوری پیکربندی کنید که در runlevel مورد نظر اجرا نشود (به صورتی که فراخوانیهای مربوطه به آن از runlevel قبلی متوقف گردند). از آنجا که update-rc.d
خود دارای رابط جداگانهای است ممکن است بخواهید از rcconf
استفاده کنید (از بسته rcconf) که رابط کاربری بهتری فراهم کرده است.
در نهایت، init
به اجرای برنامههای کنترلی مرتبط با کنسولهای مجازی (getty
) میپردازد. یک صفحه خالی که نامکاربری را درخواست میکند نمایش مییابد، سپس برای برپایی یک نشست به اجرای login user
میپردازد.