عند إقلاع الحاسب، تعرض الرسائل العديدة التي تمر على الشاشة العديد من الإعدادات وعمليات التهيئة الجارية. قد ترغب أحياناً بتعديل هذه المرحلة قليلاً، مما يعني أنك تحتاج فهمها جيداً. هذا هو الهدف من هذا القسم.
9.1.1. نظام إقلاع systemd
حالياً، يُقدِّم systemd عملية ”init الحقيقية“، ويشرح هذا القسم نظام الإقلاع هذا.
ينفذ systemd عدة عمليات مسؤولة عن إعداد النظام: لوحة المفاتيح، التعريفات، نظم الملفات، الشبكة، الخدمات. يحافظ systemd على الرؤية العامة للنظام ككل، ولمتطلبات المكونات أيضاً. كل مكون معرف باستخدام ”ملف وحدة unit file“ (وأحياناً أكثر من ملف)؛ الصيغة العامة لهذه الملفات مشتقة من صيغة ملفات ”*.ini“ الشائع استخدامها، حيث تُجمع أزواج key = value
ضمن ترويسات [section]
. تُخزَّنُ ملفات الواحدات في /lib/systemd/system/
و/etc/systemd/system/
؛ ولها أنواع عديدة، لكننا سنركز على ”الخدمات services“ و”الأهداف targets“ هنا.
يعرف ”ملف الخدمة“ في systemd عملية يديرها systemd. يحوي هذا الملف نفس المعلومات التي كانت تحويها سكربتات init القديمة تقريباً، لكنها معرفة بطريقة تصريحية (وأكثر اختصاراً بكثير). يتولى systemd غالبية المهام المتكررة (بدء العملية وإيقافها، فحص حالتها، السجلات logging، سحب الصلاحيات، وغيرها)، أما ملف الخدمة فيذكر فقط خصوصيات العملية. على سبيل المثال، هذا ملف الخدمة الخاص بعملية 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 مهمة عرض تقارير عن مستوى التقدم progress reports، ومتابعة العمليات، وإعادة تشغيلها عند الحاجة.
يعرف ”ملف الهدف“ في systemd إحدى حالات النظام، حيث تعمل فيها مجموعة محددة من الخدمات. يمكنك اعتبارها كمكافئ للمستوى التشغيلي قديماً. أحد الأهداف هو 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 على ضمان عمل CUPS في سبيل الوصول إلى printer.target
.
بما أن ملفات الوحدات ملفات تصريحية وليست سكربتات أو برامج، فلا يمكن تنفيذها مباشرة، ولا يمكن تفسيرها إلا عن طريق 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 هي أنه يتضمن مكون للتسجيل (logging) يدعى 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 (الذي سنكتفي بتسميته init اختصاراً) عدة عمليات، وفقاً للتعليمات في الملف
/etc/inittab
. أول برنامج ينفذ هو
/etc/init.d/rcS
(التابع لمرحلة
sysinit)، وهو سكربت ينفذ جميع البرامج في المجلد
/etc/rcS.d/
.
من ضمن هذه البرامج سوف تجد –على التعاقب– برامجاً مسؤولة عن:
إعداد لوحة مفاتيح الطرفية؛
تحميل التعاريف: تحمّل النواة معظم التعاريف عند اكتشاف العتاد؛ بعدها تحمل التعاريف الإضافية آلياً إذا كانت الوحدات الموافقة لها مذكورة في /etc/modules
؛
التحقق من سلامة نظام الملفات؛
ربط الأقسام المحلية؛
إعداد الشبكة؛
ربط نظم الملفات الشبكية (NFS).
بعد هذه المرحلة، تتولى init
التحكم وتبدأ تشغيل البرامج المفعلة في مستوى التشغيل الافتراضي (وهو عادة المستوى 2)، حيث تنفذ /etc/init.d/rc 2
، وهو سكربت يشغل جميع الخدمات المذكورة في المجلد /etc/rc2.d/
والتي تبدأ أسماؤها بالحرف ”S“. كان يستخدم العدد المؤلف من خانتين الذي يتلو الحرف قديماً لتحديد ترتيب تشغيل الخدمات، لكن حالياً أصبح نظام الإقلاع الافتراضي يعتمد على insserv
، الذي يجدول كل شيء آلياً حسب اعتماديات السكربتات. بالتالي على كل سكربت إقلاعي أن يصرح عن الشروط التي يجب تلبيتها عند تشغيل أو إيقاف الخدمة (إذا كان يجب تشغيل الخدمة قبل أو بعد خدمة أخرى مثلاً)؛ بعدها تشغلهم init
بالترتيب الذي يحقق هذه الشروط. لم يعد الترقيم الثابت يؤخذ بعين الاعتبار إذن (لكن أسماء السكربتات يجب أن تبدأ دائمًا بحرف ”S“ يتبعه خانتين من الأرقام ثم الاسم الفعلي للسكربت الذي يستخدم مع الاعتماديات). عموماً، يبدأ تشغيل الخدمات الأساسية (مثل خدمة rsyslog
التي تجمع السجلات، أو خدمة تعيين المنافذ portmap
) أولاً، تليها الخدمات القياسية والواجهة الرسومية (gdm3
).
يسمح نظام الإقلاع الاعتمادي هذا بأتمتة عملية إعادة الترقيم، وهذه عملية متعبة جداً لو كانت ستتم يدوياً، كما يحد من الأخطاء البشرية، بما أن الجدولة تجري وفقاً للقيود المفروضة. هناك أيضاً ميزة أخرى، وهي أن تشغيل الخدمات يمكن أن يتم على التوازي إذا كانت مستقلة عن بعضها، وهذا يسرع عملية الإقلاع.
تفرق init
بين عدة مستويات تشغيلية، بحيث يمكن التبديل من أحد هذه المستويات إلى الآخر بالأمر telinit new-level
. تبدأ init
فوراً تنفيذ /etc/init.d/rc
مرة ثانية ولكن في المستوى التشغيلي الجديد. بعدها يبدأ هذا السكربت تشغيل الخدمات الناقصة وإيقاف الخدمات التي لم تعد مرغوبة. لإتمام هذه المهمة، يستند هذا السكربت على محتويات /etc/rcX.d
(حيث X تمثل المستوى الجديد). السكربتات التي تبدأ بالحرف ”S“ (من كلمة ”Start“) هي الخدمات التي يجب تشغيلها؛ أما التي تبدأ بالحرف ”K“ (من كلمة ”Kill“) فهي الخدمات التي يجب إيقافها. لا يشغل السكربت أي خدمة كانت فعالة مسبقاً في المستوى التشغيلي السابق.
افتراضياً، يستخدم نظام إقلاع System V في دبيان أربعة مستويات تشغيلية:
المستوى 0 يستخدم مؤقتاً فقط أثناء إيقاف تشغيل الحاسب. ولذلك فهو لا يحوي إلا عدة سكربتات ”K“ فقط.
المستوى 1، ويعرف أيضاً بوضع المستخدم الوحيد single-user mode، وهو يمثل النظام في وضع الأداء المنخفض؛ فهو يُحَمِّل الخدمات الأساسية فقط، وهو يستخدم لأغراض الصيانة بعيداً عن تفاعل المستخدمين.
المستوى 2 هو مستوى العمل الطبيعي، الذي يتضمن خدمات الشبكة، والواجهة الرسومية، واتصالات المستخدمين، الخ.
المستوى 6 يشبه المستوى 0، عدا أنه يستخدم في طور إيقاف التشغيل الذي يسبق إعادة الإقلاع.
هناك مستويات تشغيل أخرى، بالأخص المستويات من 3 إلى 5. افتراضياً تعمل هذه المستويات مثل المستوى 2 تماماً، لكن يستطيع مدير النظام تعديلها (بإضافة أو حذف سكربتات في مجلد /etc/rcX.d
الموافق) لتكييفها مع حاجاته الخاصة.
كافة السكربتات المخزنة في مجلدات /etc/rcX.d
المختلفة هي في الحقيقة روابط رمزية فقط —يُنشِئها البرنامج update-rc.d
عند تثبيت الحزمة— تشير إلى السكربتات الفعلية المخزنة في /etc/init.d/
. يستطيع مدير النظام ضبط الخدمات المتاحة في كل مستوى تشغيلي من خلال إعادة استدعاء update-rc.d
مع البارامترات المعدلة. تشرح صفحة الدليل update-rc.d(1) صيغة استخدامها بالتفصيل. نرجو أن تلاحظ أن إزالة جميع الروابط الرمزية (باستخدام البارامتر remove
) ليست طريقة جيدة لتعطيل الخدمة. بل عليك إعدادها بحيث لا تعمل في المستوى التشغيلي المطلوب بكل بساطة (مع الحفاظ على الاستدعاءات الموافقة لإيقافها في حال كانت الخدمة تعمل في المستوى التشغيلي السابق). بما أن واجهة update-rc.d
متشابكة نوعاً ما، فقد تفضل استخدام rcconf
(من الحزمة rcconf) الذي يوفر واجهة أليفة للمستخدم.
أخيراً، تبدأ init
تشغيل البرامج لمختلف الطرفيات الظاهرية (getty
). بعدها تعرض سطر أوامر، الذي ينتظر إدخال اسم المستخدم، ثم تنفذ login user
لبدء جلسة عمل.