systemd 是 Linux 下一个与 SysV 和 LSB 初始化脚本兼容的系统和服务管理器。systemd 使用 socket 和 D-Bus 来开启服务,提供基于守护进程的按需启动策略,保留了 Linux cgroups 的进程追踪功能,支持快照和系统状态恢复,维护挂载和自挂载点,实现了各服务间基于从属关系的一个更为精细的逻辑控制,拥有前卫的并行性能。systemd 无需经过任何修改便可以替代 sysvinit 。更多信息,请参考视频:http://linuxconfau.blip.tv/file/4696791/ 和 http://www.youtube.com/watch?v=TyMLi8QF6sw
为什么是 systemd?
http://0pointer.de/blog/projects/why.html
介绍
systemd 开启和监督整个系统是基于 unit 的概念。unit 是由一个与配置文件对应的名字和类型组成的(例如:avahi.service unit 有一个具有相同名字的配置文件,是守护进程Avahi 的一个封装单元)。unit 有以下几种类型:
service
:守护进程的启动、停止、重启和重载是此类 unit 中最为明显的几个类型。socket
:此类 unit 封装系统和互联网中的一个 socket 。当下,systemd 支持流式、数据报和连续包的 AF_INET、AF_INET6、AF_UNIX socket 。也支持传统的 FIFOs 传输模式。每一个 socket unit 都有一个相应的服务 unit 。相应的服务在第一个“连接”进入 socket 或 FIFO 时就会启动(例如:nscd.socket 在有新连接后便启动 nscd.service)。device
:此类 unit 封装一个存在于 Linux 设备树中的设备。每一个使用 udev 规则标记的设备都将会在 systemd 中作为一个设备 unit 出现。udev 的属性设置可以作为配置设备 unit 依赖关系的配置源。mount
:此类 unit 封装系统结构层次中的一个挂载点。automount
:此类 unit 封装系统结构层次中的一个自挂载点。每一个自挂载 unit 对应一个已挂载的挂载 unit (需要在自挂载目录可以存取的情况下尽早挂载)。target
:此类 unit 为其他 unit 进行逻辑分组。它们本身实际上并不做什么,只是引用其他 unit 而已。这样便可以对 unit 做一个统一的控制。(例如:multi-user.target 相当于在传统使用 SysV 的系统中运行级别5);bluetooth.target 只有在蓝牙适配器可用的情况下才调用与蓝牙相关的服务,如:bluetooth 守护进程、obex 守护进程等)snapshot
:与 target unit 相似,快照本身不做什么,唯一的目的就是引用其他 unit 。
文档
systemd 拥有丰富的文档。参考 http://0pointer.de/blog/projects/systemd-docs.html
特性
systemd 提供以下特性:
- 使用 socket 的前卫的并行性能:为了加速整个系统启动和并行启动更多的进程,systemd 在实际启动守护进程之前创建监听 socket ,然后传递 socket 给守护进程。在系统初始化时,首先为所有守护进程创建 socket ,然后再启动所有的守护进程。如果一个服务因为需要另一个服务的支持而没有完全启动,而这个连接可能正在提供服务的队列中排队,那么这个客户端进程在这次请求中就处于阻塞状态。但是只有这一个客户端进程在这一次请求中阻塞。服务间的依赖关系也不再需要通过配置来实现真正的并行启动(因为一次开启了所有的 socket ,如果一个服务需要其他的服务,它显然可以连接到相应的 socket)。
- D-Bus 激活策略启动服务:通过使用总线激活策略,服务可以在接入时马上启动。同时,总线激活策略使得系统可以用微小的消耗实现 D-Bus 服务的提供者与消费者的同步开启请求。(同时开启多个服务,如果一个比总线激活策略中其他服务快就在 D-Bus 中排队其请求,直到其他管理确定自己的服务信息为止)
- 提供守护进程的按需启动策略
- 保留了使用 Linux cgroups 进程的追踪功能:每一个执行了的进程获得它自己的一个 cgroup ,配置 sysytemd 使其可以存放在 cgroup 中已经经过外部配置的服务非常简单。(如使用 libcgroups utilities )
- 支持快照和系统状态恢复:快照可以用来保存/恢复系统初始化时所有的服务和 unit 的状态。它有两种主要的使用情况:允许用户暂时进入一个像 "Emergency Shell" 的特殊状态,终止当前的服务;提供一个回到先前状态的简单方法,重新启动先前暂时终止的服务。
- 维护挂载和自挂载点:systemd 监视所有的挂载点的进出情况,也可以用来挂载或卸载挂载点。
/etc/fstab
也可以作为这些挂载点的一个附加配置源。通过使用comment=
fstab 选项你甚至可以标记/etc/fstab
条目使其成为由 systemd 控制的自挂载点。
- 实现了各服务间基于依赖关系的一个精细的逻辑控制:systemd 支持服务(或 unit)间的多种依赖关系。在 unit 配置文件中使用 After/Before、Requires 和 Wants 选项可以固定 unit 激活的顺序。Requires 和 Wants 表示一个正向(强制或可选)的需求和依赖关系,Conflicts 表示一个负向的需求和依赖关系。其他选项较少用到。如果一个 unit 需要启动或关闭,systemd 就把它和它的依赖关系添加到临时执行列表,然后确认它们的相互关系是否一致(或所有unit 的先后顺序是否含有循环)。如果答案是否的话,systemd 将尝试修复它,删除可以消除循环的无用工作。
另外:
- 它可以控制由它催生的每一个程序:The environment, resource limits, working and root directory, umask, OOM killer adjustment, nice level, IO class and priority, CPU policy and priority, CPU affinity, timer slack, user id, group id, supplementary group ids, readable/writable/inaccessible directories, shared/private/slave mount flags, capabilities/bounding set, secure bits, CPU scheduler reset of fork, private /tmp name-space, cgroup control for various subsystems. Also, you can easily connect
stdin/stdout/stderr
of services tosyslog
,/dev/kmsg
, arbitrary TTYs. If connected to a TTY for input systemd will make sure a process gets exclusive access, optionally waiting or enforcing it.
- 本地配置文件使用与著名的
.desktop
文件相近的语法:很多软件架构中都有这个简单的语法的分析器。它也可以借用已有的国际化的服务描述工具,语法都是相似的,没有必要再学习新的语法。
(……更多高级特性)
- 与 SysV 初始化脚本兼容:如果可能,它会利用 LSB 和 Red Hat chkconfig 的头信息内容,否则,就使用其他可用信息,如:
/etc/rc.d
。这些初始化脚本仅仅是作为一个附加的配置源,以减少 sysytemd 服务固有的路径数目。
/etc/fstab
配置文件:这只是另一个配置源。通过使用comment=
fstab 选项标记/etc/fstab
条目,使 systemd 可以控制自挂载点。
- 支持简单的模板/实例机制:例如只有一个作为示例的
getty@.service
文件,而不是为六个 getty 都准备一个配置文件。接口部分甚至可以被直接继承,也就是说,可以简单的调用 avahi-autoipd@eth0.service 服务配置 dhcpcd@eth0.service ,使得字符串 eth0 的值可以直接通过通配符匹配得到。
- 在一定程度上兼容
/dev/initctl
。这个兼容性实际上是为了执行 FIFO-activated 服务。(只是简单地把原先的请求转换成为 D-Bus 请求)事实上,这也意味着旧的 Upstart 和 sysvinit 中的shutdown
、poweroff
和其他相似命令可以在 systemd 中继续使用。
- 与
utmp
和wtmp
兼容。(在一定程度上远不只是为了全面,想想今天的utmp
和wtmp
让人是多么的敬而远之吧)
更多详细信息,请参看开发者博客 A short list of other feathers 。
工具
systemctl
:用作内省和控制 systemd 系统和服务管理器的状态。systemd-cgls
:以树形递归显示选中的 Linux 控制组结构层次。systemadm
:一个 systemd 系统和服务管理器的图形化前端。是 systemd-gtk 软件包的一部分。这还只是前期版本,尚需完善。除非你是一个开发者,否则请不要使用它。
更多详细内容请参看手册页。
内核启动命令行
在系统启动时 systemd 默认激活 default.target ,它的工作就是按照依赖关系来激活服务和调用其他 unit 。
为了重载需要激活的 unit ,systemd 通过 systemd.unit=
命令行选项解析其自己的 kernel 命令行参数。这可以用来临时启动系统到一个不同的启动 unit 。传统的 run-levels 被下面的取代:
systemd.unit=rescue.target
是一个设置基本系统和救援 shell 的特殊 target unit (与运行级1相似);systemd.unit=emergency.target
与传递保留参数的 init=/bin/sh
给系统使系统从该状态启动相似;systemd.unit=multi-user.target
设置一个非图形化的多用户系统;
systemd.unit=graphical.target
设置一个图形化的登录界面。
关于特殊的 systemd 启动 unit 的详细内容,请参看 systemd.special
手册页。
Fedora 中 systemd 的开发状态
在 Fedora 14 的特性中,systemd 是作为一个技术预览。在 Fedora 15 中替代 Upstart 作为默认管理器。
System V init 与 systemd 的对接
大量(但不是全部)核心服务(在 /lib/systemd/system
中有的,可以通过 http://fedoraproject.org/wiki/User:Johannbg/QA/Systemd/compatability 检查它们的状态)已经转换到了 systemd 中。预计在 Fedora 16 时完成所有转换工作。详情请参考
http://fedoraproject.org/wiki/Features/SysVtoSystemd 。systemd 完全兼容原始系统的初始化脚本。
systemd 的服务管理程序
systemctl
是最主要的工具。它融合 service
和 chkconfig
的功能于一体。你可以使用它永久性或只在当前会话中启用/禁用服务。
下面命令用于列出正在运行的服务或其他:
systemctl
更多详细信息请参考手册页(man systemctl)。systemd-cgls
以树形列出正在运行的进程。它可以递归显示给定控制组内容。详情请参阅 systemd-cgls
手册页。
如何启动/关闭、开启/禁用服务?
运行一个服务:
systemctl start foo.service
关闭一个服务:
systemctl stop foo.service
重启一个服务:
systemctl restart foo.service
显示一个服务(无论运行与否)的状态:
systemctl status foo.service
在开机时启用一个服务:
systemctl enable foo.service
在开机时禁用一个服务:
systemctl disable foo.service
检查一个是否已开机启用:
systemctl is-enabled foo.service; echo $?
0 表示已开机启用,1 表示没有开机启用。
更多详情请参看 systemctl
手册。
如何改变运行级别?
systemd 使用比 sysvinit 的运行级更为自由的 target 概念作为替代。
第 3 运行级用 myti-user.target 替代。第 5 运行级用 graphical.target 替代。runlevel3.target 和 runlevel5.target 分别是指向 muti-user.target 和 graphical.target 的符号链接。
你可以使用下面的命令切换到“运行级 3 ”:
systemctl isolate multi-user.target (or) systemctl isolate runlevel3.target
你也可以使用下面的命令切换到“运行级 5 ”:
systemctl isolate graphical.target (or) systemctl isolate runlevel5.target
如何改变默认运行级别?
systemd 使用链接来指向默认的运行级别。在创建新的链接前,你可以通过下面命令删除存在的链接:
rm /etc/systemd/system/default.target
默认切换到运行级 3 :
ln -sf /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
默认切换到运行级 5 :
ln -sf /lib/systemd/system/graphical.target /etc/systemd/system/default.target
systemd 不使用/etc/inittab
文件。
如何查看当下运行级别?
runlevel
命令在 systemd 下仍然可以工作。你可以继续使用它,尽管 systemd 使用 'target' 概念(多个的 'target' 可以同时激活)替换了之前系统的 runlevel 。等价的 systemd 命令是
systemctl list-units --type=target
如何关机?
你可以使用
poweroff
更多可行的命令是: halt -p
、 init 0
、 shutdown -P now
需要注意的是,在之前的 Fedora 发布版中 halt
与 poweroff
的效果一样。但是 systemd 区别对待这两项,因而,没有参数的 halt
做的就是像它说的那样(停止)——仅仅停止系统而不关机。
service
命令兼容 systemd 吗?
兼容。service
经过修改可以在处理 systemd 服务时调用 systemctl
实现。因而下面的命令所做的事情相同
service NetworkManager stop
(or)
systemctl stop NetworkManager.service
chkconfig
命令兼容 systemd 吗?
兼容,如果是开启/关闭服务,兼容性保证两种方式都可以运行。不过 chkconfig
经过修改使得在处理 systemd 服务时调用 systemctl
工具。同样,在处理传统 sysv 初始化文件时 systemd
自动调用 chkconfig
。
因此,下面的命令做的事情是一样的
chkconfig NetworkManager off
(or)
systemctl disable NetworkManager.service
chkconfig --list
不会列出 systemd 服务,只列出 Sys V 服务。chkconfig
的输出结果里附带了对此的说明信息。
system-config-services
与 systemd 兼容吗?
Feodra 15 的 system-config-services 版本也可以处理 systemd 的服务文件。如果你遇到问题,直接报告一个 bug 。
如何改变默认 getty 数目?
添加一个新的 getty :
只需要在 getty.target.wants/
目录下新建一个链接到 getty 的示例即可:
ln -sf /lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@tty9.service systemctl daemon-reload systemctl start getty@tty9.service
删除一个 getty :
直接删掉 getty.target.wants/
目录下你不想要的哪个 getty 链接即可:
rm /etc/systemd/system/getty.target.wants/getty@tty5.service /etc/systemd/system/getty.target.wants/getty@tty6.service systemctl daemon-reload systemctl stop getty@tty5.service getty@tty6.service
systemd 不使用 /etc/inittab
文件。
虚拟终端如何设置自动登录?
首先创建一个新的类似与 getty@.service 的服务:
# cp /lib/systemd/system/getty@.service \ /etc/systemd/system/autologin@.service # ln -s /etc/systemd/system/autologin@.service \ /etc/systemd/system/getty.target.wants/getty@tty8.service
然后编辑 ExecStart、Restart 和 Alias 的值,如:
... ExecStart=-/sbin/mingetty --autologin USERNAME %I Restart=no ... Alias=getty.target.wants/getty@tty8.service
最后重新加载守护进程,运行服务:
systemctl daemon-reload systemctl start getty@tty8.service
需要注意的是,如果你退出了 tty8 的会话,你需要等到下次重新启动才能使用,除非你给 Restart 的值是 'always' ,这样你可以使用systemctl
手动开启(但是出于安全考虑,强烈建议你不要那么做)。
如何定制或增加一个自定义 unit 文件?
unit 文件在 /etc/systemd/system
下的优先级要高于 /lib/systemd/system
下的。按照个人的需求从后者移动到前者并进行自定义修改。
如果一行以 .include
开始,后接文件名,那么该文件在此时被解析为特殊文件。请确保包含的文件在指令前有适当的章节头信息。
如果可能的话,你应当使用 .include
声明 unit 文件而不是在 /lib/systemd/system
下复制整个 unit 文件到 /etc/systemd/system
目录下。这样你才可以在将来升级软件包时正确地升级未改变的指令。
在使用 .include
和指令时需要小心,因为它可以有多次定义(像 EnvironmentFile=
一样)。由于我们只能添加新指令而不能删除已定义的指令,此时,我们就必须从 /lib/systemd/system
复制整个文件到 /etc/systemd/system
中去。
假设我们有一个 lighttpd 服务,我们现在想降低它的 niceness 值。我们需要做的就只是添加 Nice=-5
到 lighttpd.service 文件中。我们可以通过复制整个文件 /lib/systemd/system/lighttpd.service
到 /etc/systemd/system/lighttpd.service
或者在 /etc/systemd/system/lighttpd.service
中创建如下文件做到
.include /lib/systemd/system/lighttpd.service [Service] Nice=-5
不要忘记在编辑一个 unit 文件后使用 systemdctl daemon-reload
重载 systemd 守护进程。
如何调试系统事件?
参看 How_to_debug_Systemd_problems
预读功能
systemd 有内置的预读功能(默认升级时未启用),它可以提高开机速度,但具体提升幅度视个人硬件而定。 要使用它,使用命令:
systemctl enable systemd-readahead-collect.service systemctl enable systemd-readahead-replay.service
关于 /usr
分区的警告
详情请参考: http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken 和 http://cgit.freedesktop.org/systemd/tree/README
man
手册
systemd 有丰富的文档,其中也包括一些 man
手册页。其网页版地址是:
http://0pointer.de/public/systemd-man/
参考
- http://0pointer.de/blog/projects/ - Lennart's blog has lots of information about systemd. Lennart is the primary systemd developer
- http://www.freedesktop.org/wiki/Software/systemd/FrequentlyAskedQuestions
- http://www.freedesktop.org/wiki/Software/systemd/TipsAndTricks
- Features Fedora 15:systemd
- Project homepage
- Interview with the developer
- cgroups