回到Linux基础系列文章大纲 回到Systemd系列文章大纲 回到Shell系列文章大纲
systemd时代的运行级别 在CentOS 6及之前的版本中有运行级别的概念,Systemd系统内没有直接定义运行级别的概念,但是通过Target Unit兼容模拟了运行级别。
可以查看/usr/lib/systemd/system/下的一些target文件。为了节省篇幅,下面我列出了部分target:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 $ ls -l /usr/lib/systemd/system/*.target | grep -o '/.*' /usr/lib/systemd/system/default.target -> graphical.target /usr/lib/systemd/system/runlevel0.target -> poweroff.target /usr/lib/systemd/system/runlevel1.target -> rescue.target /usr/lib/systemd/system/runlevel2.target -> multi-user.target /usr/lib/systemd/system/runlevel3.target -> multi-user.target /usr/lib/systemd/system/runlevel4.target -> multi-user.target /usr/lib/systemd/system/runlevel5.target -> graphical.target /usr/lib/systemd/system/runlevel6.target -> reboot.target /usr/lib/systemd/system/emergency.target /usr/lib/systemd/system/rescue.target /usr/lib/systemd/system/multi-user.target /usr/lib/systemd/system/graphical.target /usr/lib/systemd/system/halt.target /usr/lib/systemd/system/poweroff.target /usr/lib/systemd/system/shutdown.target /usr/lib/systemd/system/reboot.target /usr/lib/systemd/system/ctrl-alt-del.target -> reboot.target
而target的主要作用是对服务进行分组、归类。所以,只需要定义几个代表不同运行级别的target,并在不同的target中放入不同的服务程序即可(除了服务程序还可以包含其它的Unit)。
target又是如何对服务进行分组、归类的呢?作为初步了解,可在/etc/systemd/system中寻找答案。在此目录下,有一些*.target.wants
目录,该目录定义了该target中包含了哪些Unit,systemd会在处理到对应target时会寻找wants后缀的目录,并加载启动该目录下的所有Unit,这就是target对服务(及其它Unit)分组的方式。
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 $ ls -1F /etc/systemd/system/ basic.target.wants/ default.target@ default.target.wants/ getty.target.wants/ local-fs.target.wants/ multi-user.target.wants/ nginx.service.d/ remote-fs.target.wants/ sockets.target.wants/ sysinit.target.wants/ system-update.target.wants/ $ ls -1 /etc/systemd/system/sysinit.target.wants/ cgconfig.service lvm2-lvmetad.socket lvm2-lvmpolld.socket lvm2-monitor.service rhel-autorelabel-mark.service rhel-autorelabel.service rhel-domainname.service rhel-import-state.service rhel-loadmodules.service $ ls -1 /etc/systemd/system/multi-user.target.wants/ auditd.service crond.service irqbalance.service mysqld.service nfs-client.target postfix.service remote-fs.target rhel-configure.service rpcbind.service rsyslog.service sshd.service tuned.service
之所以有这些wants目录,并且其中有一些Unit文件,是因为在Service配置文件(或其它Unit)中的[Install]
段落使用了WantedBy
指令。例如:
1 2 3 4 5 6 7 8 9 $ cat /usr/lib/systemd/system/sshd.service [Unit] ...... [Service] ...... [Install] WantedBy=multi-user.target
当使用systemctl enable Unit_Name
让Unit_Name开机自启动时,会寻找该[Install]
中的WantedBy和RequiredBy,并在对应的/etc/systemd/system/xxx.target.wants
或/etc/systemd/system/xxx.target.requires
目录下创建软链接。
如果Service配置文件中没有定义WantedBy和RequiredBy,则systemctl enable
操作不会有任何效果。
此外,可以在target配置文件内部使用Wants、Requires
等表示依赖含义的指令来定义该target依赖哪些Unit。
例如:
1 2 3 4 5 6 $ cat /usr/lib/systemd/system/sysinit.target [Unit] Description=System Initialization Documentation=man:systemd.special(7) Conflicts=emergency.service emergency.target Wants=local-fs.target swap.target
.target
文件中Wants
指令定义的更符合依赖的含义,而.target.wants
目录更倾向于表明该target中归类了哪些要运行的服务。
比如负责系统环境初始化的sysinit.target,其中的Wants指令定义了必须先运行且成功运行文件系统相关任务(local-fs.target和swap.target)后才运行sysinit.target,也就是开始启动.target.wants
目录下的Unit。
执行systemctl list-units --type target
可以查看系统当前已经加载的所有target,包括那些开机自启动过程中启动的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 $ systemctl list-units --type target UNIT LOAD ACTIVE SUB DESCRIPTION basic.target loaded active active Basic System cryptsetup.target loaded active active Local Encrypted Volumes getty.target loaded active active Login Prompts local-fs-pre.target loaded active active Local File Systems (Pre) local-fs.target loaded active active Local File Systems multi-user.target loaded active active Multi-User System network-online.target loaded active active Network is Online network-pre.target loaded active active Network (Pre) network.target loaded active active Network paths.target loaded active active Paths remote-fs.target loaded active active Remote File Systems slices.target loaded active active Slices sockets.target loaded active active Sockets swap.target loaded active active Swap sysinit.target loaded active active System Initialization timers.target loaded active active Timers
除了上面展示的target,在/usr/lib/systemd/system目录下还有很多target。而且,只要用户想要对一类Unit进行分组归类,那么也可以自己定义target。
但需要明确的是,target可分为两类 :
可直接切换的target(模拟运行级别)
不可直接切换的target
切换是什么意思?比如从当前的运行级别3切换到运行级别5,将会启动运行级别5上的所有程序以及依赖程序,并停止当前已启动但运行级别5不需要的服务程序。这就是运行级别的切换,只是停止一些服务(或程序)、并启动另外一些服务而已。
切换target也一样,比如切换到graphical.target时,会启动目标graphical.target需要的所有服务,并停止当前已运行但目标target不需要的服务。
切换target的方式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 systemctl isolate Target_Name systemctl isolate default.target systemctl isolate rescue.target systemctl default systemctl resuce systemctl emergency systemctl halt systemctl poweroff systemctl reboot
可查看或设置默认的运行级别:
1 2 systemctl get-default systemctl set-default Target_Name
设置默认运行级别,实际上是创建/etc/systemd/system/default.target指向对应target配置文件的软链接。
比如:
1 2 3 $ systemctl set-default multi-user.target Removed symlink /etc/systemd/system/default.target. Created symlink from /etc/systemd/system/default.target to /usr/lib/systemd/system/multi-user.target.
target是否可直接切换,取决于target配置文件中是否定义了AllowIsolate=yes
指令。比如multi-user.target是模拟运行级别的target,肯定允许直接切换,而network.target定义的是网络启动任务,肯定不可以直接切换。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 $ systemctl cat multi-user.target [Unit] Description=Multi-User System Documentation=man:systemd.special(7) Requires=basic.target Conflicts=rescue.service rescue.target After=basic.target rescue.service rescue.target AllowIsolate=yes $ systemctl show -p AllowIsolate network.target AllowIsolate=no