زمانی که رایانه را راهاندازی میکنید، پیامهای زیادی که در کنسول به شما نمایش داده میشوند نشاندهنده عملیات خودکار راهاندازی و پیکربندی سیستم هستند. شاید بعضی وقتها بخواهید تغییری در این مرحله ایجاد کنید، که به معنای درک اولیه صحیح از آن است. هدف این قسمت نیز همین است.
On systems with a BIOS, first, the BIOS takes control of the computer, initializes the controllers and hardware, detects the disks, and bridges everything together. Then it looks up the Master Boot Record (MBR) of the first disk in the boot order and loads the code stored there (first stage). This code then launches the second stage and finally executes the bootloader.
In contrast to the BIOS, UEFI is more sophisticated, it knows filesystems and can read the partition tables. The interface searches the system storage for a partition labeled with a specific globally unique identifier (
GUID) that marks it as the
EFI System Partition (
ESP), where the bootloaders, boot managers, UEFI shell, etc., are located, and launches the desired bootloader. If Secure Boot is enabled, the boot process will verify authenticity of the EFI binaries there by signature (thus
grub-efi-arch-signed is required in this case). The UEFI specification also defines support for booting in legacy BIOS mode. This is called the
Compatibility Support Module (
CSM). If CSM is enabled, it will attempt to boot from a drive's MBR. However, many new systems do no longer support the CSM mode.
In both cases then the actual bootloader takes over, finds either a chained bootloader or the kernel on the disk, loads, and executes it. The kernel is then initialized, and starts to search for and mount the partition containing the root filesystem, and finally executes the first program — init
. Frequently, this “root partition” and this init
are, in fact, located in a virtual filesystem that only exists in RAM (hence its name, “initramfs”, formerly called “initrd” for “initialization RAM disk”). This filesystem is loaded in memory by the bootloader, often from a file on a hard drive or from the network. It contains the bare minimum required by the kernel to load the “true” root filesystem: this may be driver modules for the hard drive, or other devices without which the system cannot boot, or, more frequently, initialization scripts and modules for assembling RAID arrays, opening encrypted partitions, activating LVM volumes, etc. Once the root partition is mounted, the initramfs hands over control to the real init, and the machine goes back to the standard boot process.
9.1.1. سیستم راهانداز systemd
“init حقیقی” توسط systemd ارائه شده است که این قسمت به بررسی آن میپردازد.
Systemd executes several processes, in charge of setting up the system: keyboard, drivers, filesystems, network, services. It does this while keeping a global view of the system as a whole, and the requirements of the components. Each component is described by a “unit file” (sometimes more); the general syntax is derived from the widely-used “*.ini files“ syntax, with key = value
pairs grouped between [section]
headers. Unit files are stored under /lib/systemd/system/
and /etc/systemd/system/
; they come in several flavors, but we will focus on “services” and “targets” here.
A systemd “.service
file” describes a process managed by systemd. It contains roughly the same information as old-style init-scripts, but expressed in a declaratory (and much more concise) way. Systemd handles the bulk of the repetitive tasks (starting and stopping the process, checking its status, logging, dropping privileges, and so on), and the service file only needs to fill in the specifics of the process. For instance, here is the service file for SSH:
[Unit]
Description=OpenBSD Secure Shell server
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run
[Service]
EnvironmentFile=-/etc/default/ssh
ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/usr/sbin/sshd -t
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
Type=notify
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
Alias=sshd.service
The [Unit]
section contains generic information about the service, like its description and manual page resources, as well as relations (dependency and order) to other services. The [Service]
part contains the declarations related to the service execution (starting, stopping, killing, restarting), directories and configuration file(s) used. The last section, [Install]
, again carries generic information into which targets to install the service and, in this case, the alias that can be used instead of the service name. As you can see, there is very little code in there, only declarations. Systemd takes care of displaying progress reports, keeping track of the processes, and even restarting them when needed. The syntax of these files is fully described in several manual pages (e.g. systemd.service(5), systemd.unit(5), systemd.exec(5), etc.).
A systemd “.target
file” describes a state of the system where a set of services are known to be operational. It can be thought of as an equivalent of the old-style runlevel. One of the pre-defined targets is local-fs.target
; when it is reached, the rest of the system can assume that all local filesystems are mounted and accessible. Other targets include network-online.target
and sound.target
(for a full list of special targets see systemd.special(7)). The dependencies of a target can be listed either within the target file (in the Requires=
line), or using a symbolic link to a service file in the /lib/systemd/system/targetname.target.wants/
directory. For instance, /etc/systemd/system/printer.target.wants/
contains a link to /lib/systemd/system/cups.service
; systemd will therefore ensure CUPS is running in order to reach 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
برای بررسی وضعیت سرویس بکار میرود.
An interesting feature of systemd is that it includes a logging component named journald
. It comes as a complement to more traditional logging systems such as syslogd
, but it adds interesting features such as a formal link between a service and the messages it generates, and the ability to capture error messages generated by its initialization sequence. The messages can be displayed later on, with a little help from the journalctl
command. Without any arguments, it simply spews all log messages that occurred since system boot; it will rarely be used in such a manner. Most of the time, it will be used with a service identifier:
#
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
The System V init system (which we'll call init for brevity) executes several processes, following instructions from the /etc/inittab
file. The first program that is executed (which corresponds to the sysinit step) is /etc/init.d/rcS
, a script that executes all of the programs in the /etc/rcS.d/
directory.
در میان آنها، برنامههای پیدرپی مرتبطی پیدا خواهید کرد:
پیکربندی صفحهکلید کنسول؛
بارگیری درایورها: اکثر ماژولهای کرنل توسط خودش هنگام شناسایی سختافزار بارگیری میشوند؛ درایورهای اضافی به صورت خودکار زمانی که ماژول مربوطه در فایل /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
) تا آنها را برای نیازهای خاص سازگار سازد.
All the scripts contained in the various /etc/rcX.d
directories are really only symbolic links — created upon package installation by the update-rc.d
program — pointing to the actual scripts which are stored in /etc/init.d/
. The administrator can fine tune the services available in each runlevel by re-running update-rc.d
with adjusted parameters. The update-rc.d(1) manual page describes the syntax in detail. Please note that removing all symbolic links (with the remove
parameter) is not a good method to disable a service. Instead you should simply configure it to not start in the desired runlevel (while preserving the corresponding calls to stop it in the event that the service runs in the previous runlevel). Since update-rc.d
has a somewhat convoluted interface, you may prefer using rcconf
(from the rcconf package) which provides a more user-friendly interface.
در نهایت، init
به اجرای برنامههای کنترلی مرتبط با کنسولهای مجازی (getty
) میپردازد. یک صفحه خالی که نامکاربری را درخواست میکند نمایش مییابد، سپس برای برپایی یک نشست به اجرای login user
میپردازد.