浅析 Linux 初始化 init 系统,第 3 部分Systemd 的使用
- UID
- 1066743
|
浅析 Linux 初始化 init 系统,第 3 部分Systemd 的使用
下面针对技术人员的不同角色来简单地介绍一下 systemd 的使用。本文只打算给出简单的描述,让您对 systemd 的使用有一个大概的理解。具体的细节内容太多,即无法在一篇短文内写全,本人也没有那么强大的能力。还需要读者自己去进一步查阅 systemd 的文档。
系统软件开发人员开发人员需要了解 systemd 的更多细节。比如您打算开发一个新的系统服务,就必须了解如何让这个服务能够被 systemd 管理。这需要您注意以下这些要点:
- 后台服务进程代码不需要执行两次派生来实现后台精灵进程,只需要实现服务本身的主循环即可。
- 不要调用 setsid(),交给 systemd 处理
- 不再需要维护 pid 文件。
- Systemd 提供了日志功能,服务进程只需要输出到 stderr 即可,无需使用 syslog。
- 处理信号 SIGTERM,这个信号的唯一正确作用就是停止当前服务,不要做其他的事情。
- SIGHUP 信号的作用是重启服务。
- 需要套接字的服务,不要自己创建套接字,让 systemd 传入套接字。
- 使用 sd_notify()函数通知 systemd 服务自己的状态改变。一般地,当服务初始化结束,进入服务就绪状态时,可以调用它。
Unit 文件的编写
对于开发者来说,工作量最大的部分应该是编写配置单元文件,定义所需要的单元。
举例来说,开发人员开发了一个新的服务程序,比如 httpd,就需要为其编写一个配置单元文件以便该服务可以被 systemd 管理,类似 UpStart 的工作配置文件。在该文件中定义服务启动的命令行语法,以及和其他服务的依赖关系等。
此外我们之前已经了解到,systemd 的功能繁多,不仅用来管理服务,还可以管理挂载点,定义定时任务等。这些工作都是由编辑相应的配置单元文件完成的。我在这里给出几个配置单元文件的例子。
下面是 SSH 服务的配置单元文件,服务配置单元文件以.service 为文件名后缀。
1
2
3
4
5
6
7
8
9
10
11
12
13
| #cat /etc/system/system/sshd.service
[Unit]
Description=OpenSSH server daemon
[Service]
EnvironmentFile=/etc/sysconfig/sshd
ExecStartPre=/usr/sbin/sshd-keygen
ExecStart=/usrsbin/sshd –D $OPTIONS
ExecReload=/bin/kill –HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s
[Install]
WantedBy=multi-user.target
|
文件分为三个小节。第一个是[Unit]部分,这里仅仅有一个描述信息。第二部分是 Service 定义,其中,ExecStartPre 定义启动服务之前应该运行的命令;ExecStart 定义启动服务的具体命令行语法。第三部分是[Install],WangtedBy 表明这个服务是在多用户模式下所需要的。
那我们就来看下 multi-user.target 吧:
1
2
3
4
5
6
7
8
9
10
| #cat multi-user.target
[Unit]
Description=Multi-User System
Documentation=man.systemd.special(7)
Requires=basic.target
Conflicts=rescue.service rescure.target
After=basic.target rescue.service rescue.target
AllowIsolate=yes
[Install]
Alias=default.target
|
第一部分中的 Requires 定义表明 multi-user.target 启动的时候 basic.target 也必须被启动;另外 basic.target 停止的时候,multi-user.target 也必须停止。如果您接着查看 basic.target 文件,会发现它又指定了 sysinit.target 等其他的单元必须随之启动。同样 sysinit.target 也会包含其他的单元。采用这样的层层链接的结构,最终所有需要支持多用户模式的组件服务都会被初始化启动好。
在[Install]小节中有 Alias 定义,即定义本单元的别名,这样在运行 systemctl 的时候就可以使用这个别名来引用本单元。这里的别名是 default.target,比 multi-user.target 要简单一些。。。
此外在/etc/systemd/system 目录下还可以看到诸如*.wants 的目录,放在该目录下的配置单元文件等同于在[Unit]小节中的 wants 关键字,即本单元启动时,还需要启动这些单元。比如您可以简单地把您自己写的 foo.service 文件放入 multi-user.target.wants 目录下,这样每次都会被默认启动了。
最后,让我们来看看 sys-kernel-debug.mout 文件,这个文件定义了一个文件挂载点:
1
2
3
4
5
6
7
8
9
10
| #cat sys-kernel-debug.mount
[Unit]
Description=Debug File Syste
DefaultDependencies=no
ConditionPathExists=/sys/kernel/debug
Before=sysinit.target
[Mount]
What=debugfs
Where=/sys/kernel/debug
Type=debugfs
|
这个配置单元文件定义了一个挂载点。挂载配置单元文件有一个[Mount]配置小节,里面配置了 What,Where 和 Type 三个数据项。这都是挂载命令所必须的,例子中的配置等同于下面这个挂载命令:
mount –t debugfs /sys/kernel/debug debugfs
配置单元文件的编写需要很多的学习,必须参考 systemd 附带的 man 等文档进行深入学习。希望通过上面几个小例子,大家已经了解配置单元文件的作用和一般写法了。
系统管理员systemd 的主要命令行工具是 systemctl。
多数管理员应该都已经非常熟悉系统服务和 init 系统的管理,比如 service、chkconfig 以及 telinit 命令的使用。systemd 也完成同样的管理任务,只是命令工具 systemctl 的语法有所不同而已,因此用表格来对比 systemctl 和传统的系统管理命令会非常清晰。
表 2. Systemd 命令和 sysvinit 命令的对照表Sysvinit 命令Systemd 命令备注service foo startsystemctl start foo.service用来启动一个服务 (并不会重启现有的)service foo stopsystemctl stop foo.service用来停止一个服务 (并不会重启现有的)。service foo restartsystemctl restart foo.service用来停止并启动一个服务。service foo reloadsystemctl reload foo.service当支持时,重新装载配置文件而不中断等待操作。service foo condrestartsystemctl condrestart foo.service如果服务正在运行那么重启它。service foo statussystemctl status foo.service汇报服务是否正在运行。ls /etc/rc.d/init.d/systemctl list-unit-files --type=service用来列出可以启动或停止的服务列表。chkconfig foo onsystemctl enable foo.service在下次启动时或满足其他触发条件时设置服务为启用chkconfig foo offsystemctl disable foo.service在下次启动时或满足其他触发条件时设置服务为禁用chkconfig foosystemctl is-enabled foo.service用来检查一个服务在当前环境下被配置为启用还是禁用。chkconfig –listsystemctl list-unit-files --type=service输出在各个运行级别下服务的启用和禁用情况chkconfig foo –listls /etc/systemd/system/*.wants/foo.service用来列出该服务在哪些运行级别下启用和禁用。chkconfig foo –addsystemctl daemon-reload当您创建新服务文件或者变更设置时使用。telinit 3systemctl isolate multi-user.target (OR systemctl isolate runlevel3.target OR telinit 3)改变至多用户运行级别。
除了表 2 列出的常见用法,系统管理员还需要了解其他一些系统配置和管理任务的改变。
首先我们了解 systemd 如何处理电源管理,命令如下表所示:
表 3,systemd 电源管理命令命令操作systemctl reboot 重启机器systemctl poweroff关机systemctl suspend待机systemctl hibernate休眠systemctl hybrid-sleep混合休眠模式(同时休眠到硬盘并待机)
关机不是每个登录用户在任何情况下都可以执行的,一般只有管理员才可以关机。正常情况下系统不应该允许 SSH 远程登录的用户执行关机命令。否则其他用户正在工作,一个用户把系统关了就不好了。为了解决这个问题,传统的 Linux 系统使用 ConsoleKit 跟踪用户登录情况,并决定是否赋予其关机的权限。现在 ConsoleKit 已经被 systemd 的 logind 所替代。
logind 不是 pid-1 的 init 进程。它的作用和 UpStart 的 session init 类似,但功能要丰富很多,它能够管理几乎所有用户会话(session)相关的事情。logind 不仅是 ConsoleKit 的替代,它可以:
- 维护,跟踪会话和用户登录情况。如上所述,为了决定关机命令是否可行,系统需要了解当前用户登录情况,如果用户从 SSH 登录,不允许其执行关机命令;如果普通用户从本地登录,且该用户是系统中的唯一会话,则允许其执行关机命令;这些判断都需要 logind 维护所有的用户会话和登录情况。
- Logind 也负责统计用户会话是否长时间没有操作,可以执行休眠/关机等相应操作。
- 为用户会话的所有进程创建 CGroup。这不仅方便统计所有用户会话的相关进程,也可以实现会话级别的系统资源控制。
- 负责电源管理的组合键处理,比如用户按下电源键,将系统切换至睡眠状态。
- 多席位(multi-seat) 管理。如今的电脑,即便一台笔记本电脑,也完全可以提供多人同时使用的计算能力。多席位就是一台电脑主机管理多个外设,比如两个屏幕和两个鼠标/键盘。席位一使用屏幕 1 和键盘 1;席位二使用屏幕 2 和键盘 2,但他们都共享一台主机。用户会话可以自由在多个席位之间切换。或者当插入新的键盘,屏幕等物理外设时,自动启动 gdm 用户登录界面等。所有这些都是多席位管理的内容。ConsoleKit 始终没有实现这个功能,systemd 的 logind 能够支持多席位。
以上描述的这些管理功能仅仅是 systemd 的部分功能,除此之外,systemd 还负责系统其他的管理配置,比如配置网络,Locale 管理,管理系统内核模块加载等,完整地描述它们已经超出了本人的能力。 |
|
|
|
|
|