Difference between revisions of "Systemd (简体中文)"

From ArchWiki
Jump to navigation Jump to search
(Update translation.)
 
(190 intermediate revisions by 23 users not shown)
Line 1: Line 1:
 
{{Lowercase title}}
 
{{Lowercase title}}
[[Category:简体中文]]
 
 
[[Category:Daemons and system services (简体中文)]]
 
[[Category:Daemons and system services (简体中文)]]
 
[[Category:Boot process (简体中文)]]
 
[[Category:Boot process (简体中文)]]
 +
[[Category:Init (简体中文)]]
 +
[[Category:Logging (简体中文)]]
 +
[[ar:Systemd]]
 +
[[de:Systemd]]
 +
[[el:Systemd]]
 
[[en:Systemd]]
 
[[en:Systemd]]
 
[[es:Systemd]]
 
[[es:Systemd]]
 +
[[fa:Systemd]]
 
[[fr:Systemd]]
 
[[fr:Systemd]]
 
[[it:Systemd]]
 
[[it:Systemd]]
 +
[[ja:Systemd]]
 +
[[pt:Systemd]]
 
[[ru:Systemd]]
 
[[ru:Systemd]]
{{Article summary start}}
+
[[zh-hant:Systemd]]
{{Article summary text|本文介绍 Systemd 的安装和配置。}}
+
{{Related articles start (简体中文)}}
{{Article summary heading|相关页面}}
+
{{Related|systemd/User (简体中文)}}
{{Article summary wiki|Systemd/Services}}
+
{{Related|systemd/Timers (简体中文)}}
{{Article summary wiki|Init to systemd cheatsheet}}
+
{{Related|systemd/Journal (简体中文)}}
{{Article summary wiki|udev (简体中文)}} - 开发者已经将 udev 整合到 systemd 中。
+
{{Related|Systemd FAQ (简体中文)}}
{{Article summary end}}
+
{{Related|Daemons#List of deamons}}
{{TranslationStatus (简体中文)|Systemd|2012-09-07|221690}}
+
{{Related|udev (简体中文)}}
摘自[http://freedesktop.org/wiki/Software/systemd 项目主页]:
+
{{Related|Improve Boot Performance (简体中文)}}
'''systemd''' 是 Linux 下的一款系统和服务管理器,兼容 SysV 和 LSB 的启动脚本(init scripts)。systemd的特性有:支持积极并行化任务;同时采用 socket 式与 [[D-Bus (简体中文)|D-Bus]] 总线式激活服务;按需启动守护进程(daemon);利用 Linux 的 [[cgroups (简体中文)|cgroups]] 监视进程;支持快照和系统恢复;维护挂载点;各服务间基于依赖关系进行精密控制。systemd 完全可以替代 Arch 默认的 sysvinit 启动系统。
+
{{Related|Allow users to shutdown}}
 +
{{Related articles end}}
 +
{{TranslationStatus (简体中文)|Systemd|2019-01-29|564454}}
 +
摘自[https://freedesktop.org/wiki/Software/systemd 项目主页]
  
{{小贴士|Arch 的启动系统正在向 systemd 迁移,原因参见[https://bbs.archlinux.org/viewtopic.php?pid=1149530#p1149530 该帖]。}}
+
:''systemd'' 是一个 Linux 系统基础组件的集合,提供了一个系统和服务管理器,运行为 PID 1 并负责启动其它程序。功能包括:支持并行化任务;同时采用 socket 式与 [[D-Bus (简体中文)|D-Bus]] 总线式激活服务;按需启动守护进程(daemon);利用 Linux 的 [[cgroups]] 监视进程;支持快照和系统恢复;维护挂载点和自动挂载点;各服务间基于依赖关系进行精密控制。''systemd'' 支持 SysV 和 LSB 初始脚本,可以替代 sysvinit。除此之外,功能还包括日志进程、控制基础系统配置,维护登陆用户列表以及系统账户、运行时目录和设置,可以运行容器和虚拟机,可以简单的管理网络配置、网络时间同步、日志转发和名称解析等。
  
另见[[Wikipedia:Systemd|维基百科上的介绍]]
+
{{注意|1= [https://bbs.archlinux.org/viewtopic.php?pid=1149530#p1149530 Arch Linux 论坛的这篇帖子] 详细地解释了 Arch Linux 迁移到 systemd 的原因。}}
  
== 迁移前需注意 ==
+
== systemd 基本工具 ==
  
* 最好先参照 [[rc.conf (简体中文)]] 按照最新格式配置 '''initscripts'''。完成后,基本上就没什么需要配置的了。
+
监视和控制systemd的主要命令是{{ic|systemctl}}。该命令可用于查看系统状态和管理系统及服务。详见{{man|1|systemctl}}。、
* 阅读[http://freedesktop.org/wiki/Software/systemd/ 该站],了解 systemd。
 
* systemd 自己有一套日志('''journal''')系统,用于代替 '''syslog'''。两者也可以共存,参见:[[#配合传统日志服务(syslog)]]。
 
* 无需担心 systemd 替换 '''cron'''、'''acpid'''、'''xinetd''' 等的计划会造成麻烦。至少,目前来讲,继续使用这些服务不会出现问题。
 
  
== 安装 ==
+
{{提示|
systemd 可以和 Arch 默认的启动系统({{pkg|initscripts}})共存,通过添加/删除[[Kernel parameters|内核参数]]{{Ic|1=init=/bin/systemd}} 切换。
+
* 在 {{ic|systemctl}} 参数中添加 {{ic|-H <用户名>@<主机名>}} 可以实现对其他机器的远程控制。该功能使用 [[SSH (简体中文)|SSH]] 连接。
 +
* [[Plasma]] 用户可以安装 ''systemctl'' 图形前端 {{AUR|systemd-kcm}}。安装后可以在 ''System administration'' 下找到。}}
  
=== 纯 systemd 安装 ===
+
=== 分析系统状态 ===
 +
 
 +
显示 '''系统状态''':
 +
 
 +
$ systemctl status
 +
 
 +
输出激活的单元:
 +
 
 +
$ systemctl
 +
 
 +
以下命令等效:
 +
 
 +
$ systemctl list-units
  
# 从[core][[Official Repositories (简体中文)|仓库]]安装 {{Pkg|systemd}}。
+
输出运行失败的单元:
# 在启动引导器添加[[Kernel parameters|内核参数]]{{Ic|1=init=/bin/systemd}}。
 
# 创建[[#原生 systemd 配置文件|systemd 配置文件]].
 
# 用 {{ic|systemctl enable ...}} 启用服务,替换 rc.conf 中的 daemons。
 
# 重启并删除 {{ic|1=init=...}} 项.
 
# 手动删除{{pkg|initscripts}},然后安装{{Pkg|systemd-sysvcompat}}.
 
  
=== 混合安装 ===
+
$ systemctl --failed
  
# 从[core]仓库安装 {{Pkg|systemd}}。
+
所有可用的单元文件存放在 {{ic|/usr/lib/systemd/system/}} {{ic|/etc/systemd/system/}} 目录(后者优先级更高)。查看所有已安装服务:
# 在启动引导器添加[[Kernel parameters|内核参数]]{{Ic|1=init=/bin/systemd}}
+
$ systemctl list-unit-files
# 建议使用[[#原生 systemd 配置文件|systemd 配置文件]]而不是 Arch 传统的配置文件。现在如果原生文件不存在,还能使用{{ic|/etc/rc.conf}}配置变量,但是未来会停止支持 rc.conf.
 
# 建议安装 {{Pkg|systemd-arch-units}},该包提供了常用系统服务的 systemd 原生服务文件。
 
# 如果要同时使用 syslog 日志文件盒 systemd 日志,请参考后面的[[# 配合传统日志服务(syslog)]].
 
  
=== Supplementary information ===
+
显示 [[cgroups|cgroup slice]], 内存和父 PID:
{{Note|1=In a pure systemd installation, installing {{pkg|systemd-sysvcompat}} removes {{pkg|sysvinit}}, permits the export of {{ic|LANG}} in {{ic|/etc/locale.conf}}, and creates symlinks to halt, reboot, etc. You must manually remove {{pkg|initscripts}} to install {{pkg|systemd-sysvcompat}} [https://bbs.archlinux.org/viewtopic.php?id=148042].}}
 
{{Tip|If you have {{ic|quiet}} in your kernel parameters, you should remove it for your first couple of systemd boots, to assist with identifying any issues during boot.}}
 
  
{{警告|udev 和很多其他系统软件要求 {{ic|/usr}} 在启动早期就挂载。如果 {{Ic|/usr}} 和根目录不在同一分区,那么必须做一些额外设置。参见 [[Mkinitcpio (简体中文)#/usr_放到单独分区|mkinitcpio相关页面]] 以及 [http://www.freedesktop.org/wiki/Software/systemd/separate-usr-is-broken freedesktop.org的相关页面]。}}
+
$ systemctl status ''pid''
  
== 原生 systemd 配置文件 ==
+
=== 使用单元 ===
{{Note|You may need to create these files.}}
 
如果下列文件不存在,{{Pkg|systemd}} 会从 {{ic|/etc/rc.conf}} 读取相关配置。这只是一个临时解决方案,建议所有系统都使用 systemd 的配置文件,这也是目前 initscripts 推荐的配置方式。
 
{{小贴士|某些文件可能需要手动创建。}}
 
  
=== 主机名 ===
+
一个单元配置文件可以描述如下内容之一:系统服务({{ic|.service}})、挂载点({{ic|.mount}})、sockets({{ic|.sockets}}) 、系统设备({{ic|.device}})、交换分区({{ic|.swap}})、文件路径({{ic|.path}})、启动目标({{ic|.target}})、由 systemd 管理的计时器({{ic|.timer}})。详情参阅 {{man|5|systemd.unit}}
设置主机名为“myhostname”:
 
{{hc|/etc/hostname|myhostname}}
 
  
=== 控制台和键盘布局 ===
+
使用 {{ic|systemctl}} 控制单元时,通常需要使用单元文件的全名,包括扩展名(例如 {{ic|sshd.service}} )。但是有些单元可以在 {{ic|systemctl}} 中使用简写方式。
{{ic|/etc/vconsole.conf}} 文件用来配置虚拟控制台,包括键盘映射和控制台字体:
+
* 如果无扩展名,systemctl 默认把扩展名当作 {{ic|.service}} 。例如 {{ic|netcfg}} 和 {{ic|netcfg.service}} 是等价的。
{{hc|/etc/vconsole.conf|<nowiki>
+
* 挂载点会自动转化为相应的 {{ic|.mount}} 单元。例如 {{ic|/home}} 等价于 {{ic|home.mount}} 。
KEYMAP=us
+
* 设备会自动转化为相应的 {{ic|.device}} 单元,所以 {{ic|/dev/sda2}} 等价于 {{ic|dev-sda2.device}} 。
FONT=lat9w-16
 
FONT_MAP=8859-1_to_uni</nowiki>}}
 
详情参阅 [[Fonts#Console_fonts|控制台字体]]和[[KEYMAP#Keyboard_layouts|Keymap]].
 
  
=== Locale ===
+
{{注意|有一些单元的名称包含一个 {{ic|@}} 标记(例如: {{ic|name@''string''.service}} ),这意味着它是模板单元 {{ic|name@.service}} 的一个 [http://0pointer.de/blog/projects/instances.html 实例]。 {{ic|''string''}} 被称作实例标识符,在 ''systemctl'' 调用模板单元时,会将其当作一个参数传给模板单元,模板单元会使用这个传入的参数代替模板中的 {{ic|%I}} 指示符。
更多内容参阅 {{ic|man locale.conf}}
 
{{hc|/etc/locale.conf|<nowiki>
 
LANG=en_US.UTF-8
 
LC_COLLATE=C</nowiki>}}
 
  
=== 时区 ===
+
在实例化之前,''systemd'' 会先检查 {{ic|name@string.suffix}} 文件是否存在(如果存在,就直接使用这个文件,而不是模板实例化)。大多数情况下,包含 {{ic|@}} 标记都意味着这个文件是模板。如果一个模板单元没有实例化就调用,该调用会返回失败,因为模板单元中的 {{ic|%I}} 指示符没有被替换。
更多内容参阅 {{ic|man 5 timezone}}。
+
}}
{{hc|/etc/timezone|Asia/Shanghai}}
 
{{Note|This file does not obviate the need for {{ic|/etc/localtime}}, which is a symbolic link to the desired time zone's zoneinfo file in {{ic|/usr/share/zoneinfo/}}.}}
 
  
=== 硬件时钟 ===
+
{{提示|
systemd 默认识别硬件时钟为协调世界时(UTC),也推荐这样设置。处理夏令时有些麻烦,如果夏令时调整发生在关机时,下次启动时时间会出现问题([http://www.cl.cam.ac.uk/~mgk25/mswish/ut-rtc.html 更多信息])。最新的内核直接从实时时钟芯片(RTC)读取时间,不使用 {{ic|hwclock}},内核把从 RTC 读取的时间当作 UTC 处理。所以如果硬件时间是地方时,系统启动一开始识别的时间是错误的,之后很快会进行矫正。这可能导致一些问题(尤其是时间倒退时)。
+
* 下面的大部分命令都可以跟多个单元名, 详细信息参见 {{man|1|systemctl}}。
 +
* {{ic|systemctl}}命令在{{ic|enable}}、{{ic|disable}}和{{ic|mask}}子命令中增加了{{ic|--now}}选项,可以实现激活的同时启动服务,取消激活的同时停止服务。
 +
* 一个软件包可能会提供多个不同的单元。如果你已经安装了软件包,可以通过{{ic|pacman -Qql ''package'' <nowiki>|</nowiki> grep systemd}}命令检查这个软件包提供了哪些单元。
 +
}}
  
如果同时安装了 Windows 操作系统([http://blogs.msdn.com/b/oldnewthing/archive/2004/09/02/224672.aspx 默认使用地方时]),那么一般 RTC 会被设置为地方时。Windows 其实也能处理 UTC,在注册表中设置下列DWORD键值为{{ic|1}}即可:
+
立即激活单元:
{{bc|HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\RealTimeIsUniversal}}
 
  
{{警告|在最新的 Windows 7、 Vista SP2 上,此设置会导致网络时间同步无法使用。而早期的版本中,此设置会导致系统[http://social.msdn.microsoft.com/forums/en-US/tabletandtouch/thread/0b872d8a-69e9-40a6-a71f-45de90c6e243/ 从睡眠、待机唤醒后出现故障]。此外,Windows 还可能因此[http://support.microsoft.com/kb/2687252 无法处理夏令时调整]。}}
+
# systemctl start <单元>
  
如果不想因此弄乱 Windows,systemd 也可以接受本地时:
+
立即停止单元:
{{hc|/etc/adjtime|<nowiki>  
+
# systemctl stop <单元>
0.0 0.0 0.0
 
0
 
LOCAL</nowiki>}}
 
{{注意|The other parameters are still needed but are ignored by systemd. (译者不理解……)}}
 
{{注意|推荐使用[[NTP (简体中文)|NTP服务]]来确保硬件时钟同步。}}
 
  
=== 开机加载内核模块 ===
+
重启单元:
systemd 读取 {{ic|/etc/modules-load.d/}} 中的配置,加载内核模块。配置文件名称通常为 {{ic|/etc/modules-load.d/<program>.conf}}。格式很简单,一行一个要读取的模块名,而空行以及第一个非空格字符为{{ic|#}}或{{ic|;}}的行会被忽略,如:
 
{{hc|/etc/modules-load.d/virtio-net.conf|<nowiki>
 
# Load virtio-net.ko at boot
 
virtio-net</nowiki>}}
 
另见:[[Kernel modules (简体中文)#选项]]
 
  
=== 禁用内核模块 ===
+
# systemctl restart <单元>
禁用内核模块的方法和 Arch 默认的 {{Pkg|initscripts}} 相同,因为该过程实际由 {{Pkg|kmod}} 处理。参见:[[Kernel modules (简体中文)#黑名单]]。
 
  
=== 临时文件 ===
+
重新加载配置:
{{ic|/usr/lib/tmpfiles.d/}} 和 {{ic|/etc/tmpfiles.d/}} 中的文件描述了 systemd-tmpfiles 如何创建、清理、删除临时文件和目录,这些文件和目录通常存放在 {{ic|/run}} 和 {{ic|/tmp}} 中。配置文件名称为 {{ic|/etc/tmpfiles.d/<program>.conf}}。此处的配置能覆盖 {{ic|/usr/lib/tmpfiles.d/}} 目录中的同名配置。
+
 
 +
# systemctl reload <单元>
 +
 
 +
输出单元运行状态:
 +
 
 +
$ systemctl status <单元>
 +
 
 +
检查单元是否配置为自动启动:
 +
$ systemctl is-enabled <单元>
 +
 
 +
开机自动激活单元:
 +
 
 +
# systemctl enable <单元>
 +
 
 +
设置单元为自动启动并立即启动这个单元:
  
临时文件通常和服务文件同时提供,以生成守护进程需要的文件和目录。例如 [[Samba (简体中文)|Samba]] 服务需要目录 {{ic|/var/run/samba}} 存在并设置正确的权限位,就象这样:
+
# systemctl enable --now ''unit''
{{hc|/usr/lib/tmpfiles.d/samba.conf|
 
D /var/run/samba 0755 root root
 
}}
 
  
此外,临时文件还可以用来在开机时向特定文件写入某些内容。比如,要禁止系统从USB设备唤醒,利用旧的 {{ic|/etc/rc.local}} 可以用 {{ic|echo USBE > /proc/acpi/wakeup}},而现在可以这么做:
+
取消开机自动激活单元:
{{hc|/etc/tmpfiles.d/disable-usb-wake.conf|
 
w /proc/acpi/wakeup - - - - USBE
 
}}
 
推荐使用新方法,因为 systemd 并不原生支持 {{ic|/etc/rc.local}}。
 
  
详情参见 {{ic|man tmpfiles.d}}。
+
# systemctl disable <单元>
  
=== 挂载网络文件系统 ===
+
禁用一个单元(禁用后,间接启动也是不可能的):
{{ic|/etc/fstab}} 中设定的网络文件系统(如 [[NFS (简体中文)|NFS]]、[[Samba (简体中文)|Samba]])无需配置即可正常工作,systemd 将确保网络文件系统在网络链接就绪后挂载。
 
  
也可以使用[[#自动挂载|自动挂载]]功能,使得网络文件系统仅在访问时挂载。添加 {{ic|1=x-systemd.device-timeout=超时时间}} 到 {{ic|/etc/fstab}} 的 <options> 部分即可。
+
# systemctl mask <单元>
  
详情参见 {{ic|man systemd.mount}}。
+
取消禁用一个单元:
  
=== 用 systemd 替代 acpid ===
+
# systemctl unmask <单元>
systemd 能够处理某些电源相关的 ACPI 事件,通过 {{ic|/etc/systemd/logind.conf}} 的下列选项配置:
 
* {{ic|HandlePowerKey}}:按下电源键后关机
 
* {{ic|HandleSleepKey}}:按下键盘Sleep键后待机
 
* {{ic|HandleLidSwitch}}:合上笔记本盖后待机
 
当选项设置为 {{ic|no-session}} 时,事件仅在无用户登录时才会触发。设置为 {{ic|any-session}} 时,仅在单用户会话时触发。详情参见 {{ic|man logind.conf}}。
 
  
不应在 [[Gnome (简体中文)|GNOME]]、[[Xfce (简体中文)|Xfce]] 这类能处理 ACPI 事件的桌面环境中使用上述选项。但如果不用图形界面,或者使用 [[i3 (简体中文)|i3]]、[[awesome (简体中文)|awesome]] 这样简单的桌面环境时,该功能可以替代 [[acpid (简体中文)|acpid]] 处理 ACPI 事件。
+
显示单元的手册页(必须由单元文件提供):
  
=== Sleep hooks ===
+
# systemctl help <单元>
运行 {{ic|systemctl suspend}} 或 {{ic|systemctl hibernate}} 命令时,Systemd 不使用[[pm-utils]]进行系统休眠。所以[[pm-utils]]钩子和用户自定义钩子都不会运行。Systemd 提供了一个类似的机制,在事件发生时,运行{{ic|/usr/lib/systemd/system-sleep/}}中的所有可执行文件。运行时会传入两个参数:
 
* {{ic|pre}} 或 {{ic|post}},标示机器是关闭还是唤醒
 
* {{ic|suspend}} 或 {{ic|hibernate}},标示使用的休眠方式
 
  
和[[pm-utils]]不通,systemd会并行执行脚本,不是按顺序执行。
+
重新载入 systemd 系统配置,扫描单元文件的变动。注意这里不会重新加载变更的单元文件。参考上面的 {{ic|reload}} 示例。
  
脚本输出通过{{ic|systemd-suspend.service}} 或 {{ic|systemd-hibernate.service}}记录,可以通过journal查看。
+
# systemctl daemon-reload
  
也可以使用 {{ic|sleep.target}}, {{ic|suspend.target}} 或 {{ic|hibernate.target}} 设置要执行的钩子脚本,详情参阅{{ic|man systemd.special}}和{{ic|man systemd-sleep}}。
+
=== 电源管理 ===
  
==== Example ====
+
安装 [[polkit]] 后才能以普通用户身份使用电源管理。
{{hc|/usr/lib/systemd/system-sleep/example.sh|<nowiki>
 
case "$1" in
 
  pre )
 
    echo going to $2 ...
 
    ;;
 
  post )
 
    echo waking up from $2 ...
 
    ;;
 
esac</nowiki>}}
 
  
=== 单元(unit) ===
+
如果你正登录在一个本地的 {{ic|systemd-logind}} 用户会话,且当前没有其它活动的会话,那么以下命令无需 root 权限即可执行。否则(例如,当前有另一个用户登录在某个 tty ), systemd 将会自动请求输入root密码。
一个单元配置文件可以描述如下内容之一:系统服务、socket、系统设备、挂载点、交换分区/文件、启动目标(target)、文件系统路径、由 systemd 管理的计时器。文件格式受 .desktop 文件启发,而最初起源是 Windows 下的 .ini 文件。详情参见 {{ic|man systemd.unit}}
 
  
== systemd 命令 ==
+
重启:
*{{ic|systemctl}}:控制 systemd 状态,包括服务的启动和停止。
 
*{{ic|systemd-cgls}}:以树形递归显示指定 Linux 控制组(cgroup)的内容
 
*{{ic|systemadm}}:控制 systemd 状态的图形前端(由 [[AUR (简体中文)|AUR]] 软件包 {{AUR|systemd-ui-git}} 提供)。
 
  
详情参见上述工具的 man 手册页。
+
$ systemctl reboot
  
{{小贴士|在 {{ic|systemctl}} 参数中添加 {{ic|-H <用户名>@<主机名>}} 可以实现对其他机器的远程控制。该过程使用 [[SSH (简体中文)|SSH]] 链接。}}
+
退出系统并关闭电源:
  
=== 分析系统状态 ===
+
$ systemctl poweroff
  
输出激活的单元:
+
待机:
  
{{bc|$ systemctl}}
+
$ systemctl suspend
  
以下命令等效:
+
休眠:
  
{{bc|$ systemctl list-units}}
+
$ systemctl hibernate
  
输出运行失败的单元:
+
混合休眠模式(同时休眠到硬盘并待机):
  
{{bc|$ systemctl --failed}}
+
$ systemctl hybrid-sleep
  
所有可用的单元文件存放在 {{ic|/usr/lib/systemd/system/}} 和 {{ic|/etc/systemd/system/}} 目录(后者优先级更高)。
+
== 编写单元文件 ==
  
=== 使用单元 ===
+
{{ic|systemd}} [https://www.freedesktop.org/software/systemd/man/systemd.unit.html 单元文件]的语法来源于 XDG 桌面项配置文件{{ic|.desktop}}文件,最初的源头则是Microsoft Windows的{{ic|.ini}}文件。单元文件可以从多个地方加载,{{ic|1=systemctl show --property=UnitPath}} 可以按优先级从低到高显示加载目录:
一个单元可以是系统服务({{ic|.service}})、挂载点({{ic|.mount}})、sockets({{ic|.sockets}})。
 
  
使用 {{ic|systemctl}} 控制单元时,通常需要使用单元文件的全名,包括扩展名(例如 {{ic|sshd.service}})。但是有些单元可以在{{ic|systemctl}}中使用简写方式。
+
* {{ic|/usr/lib/systemd/system/}} :软件包安装的单元
* 如果无后缀,sistemctl 默认后缀为{{ic|.service}}. 例如{{ic|netcfg}} 和 {{ic|netcfg.service}} 是等价的。 {{Note|This currently does not work with the commands {{ic|enable}} and {{ic|disable}}.}}
+
* {{ic|/etc/systemd/system/}} :系统管理员安装的单元
* 挂载点会自动转化为相应的{{ic|.mount}}单元。例如{{ic|/home}}等价于{{ic|home.mount}}。
 
* 设备会自动转化为相应的{{ic|.device}}单元,所以{{ic|/dev/sda2}}等价于{{ic|dev-sda2.device}}.
 
  
立即激活单元:
+
{{注意|
 +
* 当 {{ic|systemd}} 运行在[[systemd/User#How it works|用户模式]]下时,使用的加载路径是完全不同的。
 +
* systemd 单元名仅能包含 ASCII 字符,下划线和点号和有特殊意义的字符('@', '-')。其它字符需要用 C-style "\x2d" 替换。参阅 {{man|5|systemd.unit}} 和 {{man|1|systemd-escape}} 。}}
  
{{bc|# systemctl start <unit>}}
+
单元文件的语法,可以参考系统已经安装的单元,也可以参考 {{man|5|systemd.service}} 中的[https://www.freedesktop.org/software/systemd/man/systemd.service.html#Examples EXAMPLES章节]。
  
立即停止单元:
+
{{提示| 以 {{ic|#}} 开头的注释可能也能用在 unit-files 中,但是只能在新行中使用。不要在 ''systemd'' 的参数后面使用行末注释, 否则 unit 将会启动失败。}}
  
{{bc|# systemctl stop <unit>}}
+
=== 处理依赖关系 ===
  
重启单元:
+
使用 systemd 时,可通过正确编写单元配置文件来解决其依赖关系。典型的情况是,单元 {{ic|A}} 要求单元 {{ic|B}} 在 {{ic|A}} 启动之前运行。在此情况下,向单元 {{ic|A}} 配置文件中的 {{ic|[Unit]}} 段添加 {{ic|1=Requires=B}} 和 {{ic|1=After=B}} 即可。若此依赖关系是可选的,可添加 {{ic|1=Wants=B}} 和 {{ic|1=After=B}} 。请注意 {{ic|1=Wants=}} 和 {{ic|1=Requires=}} 并不意味着 {{ic|1=After=}} ,即如果 {{ic|1=After=}} 选项没有制定,这两个单元将被并行启动。
  
{{bc|# systemctl restart <unit>}}
+
依赖关系通常被用在服务(service)而不是[[#目标(target)|目标(target)]]上。例如, {{ic|network.target}} 一般会被某个配置网络接口的服务引入,所以,将自定义的单元排在该服务之后即可,因为 {{ic|network.target}} 已经启动。
  
命令单元重新读取配置:
+
=== 服务类型 ===
  
{{bc|# systemctl reload <unit>}}
+
编写自定义的 service 文件时,可以选择几种不同的服务启动方式。启动方式可通过配置文件 {{ic|[Service]}} 段中的 {{ic|1=Type=}} 参数进行设置。
  
输出单元运行状态:
+
* {{ic|1=Type=simple}} :(默认值) systemd认为该服务将立即启动。服务进程不会 fork 。如果该服务要启动其他服务,不要使用此类型启动,除非该服务是socket 激活型。
 +
* {{ic|1=Type=forking}} :systemd认为当该服务进程fork,且父进程退出后服务启动成功。对于常规的守护进程(daemon),除非你确定此启动方式无法满足需求,使用此类型启动即可。使用此启动类型应同时指定 {{ic|1=PIDFile=}},以便 systemd 能够跟踪服务的主进程。
 +
* {{ic|1=Type=oneshot}} :这一选项适用于只执行一项任务、随后立即退出的服务。可能需要同时设置 {{ic|1=RemainAfterExit=yes}} 使得 systemd 在服务进程退出之后仍然认为服务处于激活状态。
 +
* {{ic|1=Type=notify}} :与 {{ic|1=Type=simple}} 相同,但约定服务会在就绪后向 systemd 发送一个信号。这一通知的实现由 {{ic|libsystemd-daemon.so}} 提供。
 +
* {{ic|1=Type=dbus}} :若以此方式启动,当指定的 {{ic|BusName}} 出现在DBus系统总线上时,systemd认为服务就绪。
 +
* {{ic|1=Type=idle}} :{{ic|systemd}}会等待所有任务处理完成后,才开始执行 {{ic|idle}} 类型的单元。其他行为与 {{ic|1=Type=simple}} 类似。
  
{{bc|$ systemctl status <unit>}}
+
{{ic|type}} 的更多解释可以参考 [https://www.freedesktop.org/software/systemd/man/systemd.service.html#Type= systemd.service(5)]。
  
检查单元是否配置为自动启用:
+
=== 修改现存单元文件 ===
  
{{bc|$ systemctl is-enabled <unit>}}
+
为了避免和 pacman 冲突,不应该直接编辑软件包提供的文件。有两种方法可以不改动原始文件就做到修改单元文件:创建一个优先级更高的本地单元文件或创建一个片段,应用到原始单元文件之上。两种方法都需要在修改后重新加载单元,用 {{ic|systemctl edit}} 编辑单元(会自动重载单元)或通过下面命令重新加载单元:
  
开机自动激活单元:
+
# systemctl daemon-reload
  
{{bc|# systemctl enable <unit>}}
+
{{提示|
+
* {{ic|systemd-delta}} 命令用来查看哪些单元文件被覆盖、哪些被修改。系统维护的时候需要及时了解哪些单元已经有了更新。
{{注意|如果服务没有安装段落,一般意味着应该通过其它服务自动调用它们。如果真的需要手动安装,可以直接连接服务,将 foo 替换为真实的服务名:
+
* 使用 {{ic|systemctl cat ''unit''}} 可以查看单元的内容和所有相关的片段.
{{bc|# ln -s /usr/lib/systemd/system/foo.service /etc/systemd/system/graphical.target.wants/}}
 
 
}}
 
}}
  
取消开机自动激活单元:
+
==== 替换单元文件 ====
 +
 
 +
要替换 {{ic|/usr/lib/systemd/system/''unit''}}, 创建文件 {{ic|/etc/systemd/system/''unit''}} 并重新启用单元以更新链接:
 +
 
 +
# systemctl reenable ''unit''
 +
 
 +
或者运行:
 +
 
 +
# systemctl edit --full ''unit''
 +
 
 +
这将会在记事本中打开 {{ic|/etc/systemd/system/''unit''}},如果文件不存在,可以将安装的版本复制到这里,在编辑完成之后,会自动加载新版本。
 +
 
 +
{{注意|即使 Pacman 更新了新的单元文件,软件包中的版本也不会被使用,所以这个方式会增加系统维护的难度,推荐使用下面一种方法。}}
 +
 
 +
==== 附加配置片段 ====
  
{{bc|# systemctl disable <unit>}}
+
要附加配置片段,先创建名为 {{ic|/etc/systemd/system/<单元名>.d/}} 的目录,然后放入 {{ic|*.conf}} 文件,其中可以添加或重置参数。这里设置的参数优先级高于原来的单元文件。下面的更新方式比较简单:
  
显示单元的手册页(必须由单元文件提供):
+
# systemctl edit ''unit''
  
{{bc|$ systemctl help <unit>}}
+
这将会在编辑器中打开文件 {{ic|/etc/systemd/system/''unit''.d/override.conf}},编辑完成之后自动加载。
  
=== 电源管理 ===
+
{{Note|并不是所有参数都会被子配置文件覆盖。例如要修改 {{ic|1=Conflicts=}} 就必须 [https://lists.freedesktop.org/archives/systemd-devel/2017-June/038976.html 替换原始文件]。}}
  
当系统中仅有一个ConsoleKit本地用户会话时,执行下列命令无需 root 权限。否则,systemd 会要求输入 root 密码。
+
==== 重置到软件包版本 ====
  
重启:
+
要回退单元的变更,使用 {{ic|systemctl edit}} 并执行:
  
{{bc|$ systemctl reboot}}
+
# systemctl revert ''unit''
  
退出系统并停止电源(shut down and power-off):
+
==== 示例 ====
 +
例如,如果想添加一个额外的依赖,创建如下文件即可:
  
{{bc|$ systemctl poweroff}}
+
{{hc|/etc/systemd/system/<unit>.d/customdependency.conf|2=
 +
[Unit]
 +
Requires=<新依赖>
 +
After=<新依赖>}}
  
退出系统并中断(shut down and halt):
+
要修改一个非  {{ic|oneshot}} 单元的 {{ic|ExecStart}} 命令,创建下面文件:
  
{{bc|$ systemctl halt}}
+
{{hc|/etc/systemd/system/''unit''.d/customexec.conf|2=
 +
[Service]
 +
ExecStart=
 +
ExecStart=''new command''
 +
}}
  
待机:
+
修改 {{ic|ExecStart}} 前必须将其置空,参见 ([https://bugzilla.redhat.com/show_bug.cgi?id=756787#c9] 。所有可能多次赋值的变量都需要这个操作,例如定时器的 {{ic|OnCalendar}} 。
  
{{bc|$ systemctl suspend}}
+
下面是自动重启服务的一个例子:
  
休眠:
+
{{hc|/etc/systemd/system/''unit''.d/restart.conf|2=
 +
[Service]
 +
Restart=always
 +
RestartSec=30
 +
}}
  
{{bc|$ systemctl hibernate}}
+
== 目标(target) ==
  
== 启动级别(runlevel)/目标(target) ==
+
运行级别(runlevel)是一个旧的概念。现在,systemd 引入了一个和运行级别功能相似又不同的概念——目标(target)。不像数字表示的启动级别,每个''目标''都有名字和独特的功能,并且能同时启用多个。一些''目标''继承其他''目标''的服务,并启动新服务。systemd 提供了一些模仿 sysvinit 运行级别的''目标'',仍可以使用旧的 {{ic|telinit 运行级别}} 命令切换。
启动级别(runlevel)是一个旧的概念。现在,systemd 引入了一个和启动级别功能相似又不同的概念——目标(target)。不像数字表示的启动级别,每个''目标''都有名字和独特的功能,并且能同时启用多个。一些''目标''继承其他''目标''的服务,并启动新服务。systemd 提供了一些模仿 sysvinit 启动级别的''目标'',仍可以使用旧的 {{ic|telinit 启动级别}} 命令切换。
 
  
=== 获取当前启动级别/目标 ===
+
=== 获取当前目标 ===
 
不要使用 {{ic|runlevel}} 命令了:
 
不要使用 {{ic|runlevel}} 命令了:
{{bc|1=# systemctl list-units --type=target}}
+
$ systemctl list-units --type=target
  
=== 创建新目标 ===
+
=== 创建自定义目标 ===
Fedora 中,启动级别 0、1、3、5、6 都被赋予特定用途,并且都对应一个 systemd 的''目标''。然而,没有什么很好的移植用户定义的启动级别(2、4)的方法。要实现类似功能,可以以原有的启动级别为基础,创建一个新的''目标'' {{ic|/etc/systemd/system/<新目标>}}(可以参考 {{ic|/usr/lib/systemd/system/graphical.target}}),创建 {{ic|/etc/systemd/system/<新目标>.wants}} 目录,向其中加入额外服务的链接(指向 {{ic|/usr/lib/systemd/system/}} 中的单元文件)。
+
在 ''sysvinit'' 中有明确定义的运行级别(如:0、1、3、5、6)与 ''systemd'' 中特定的 ''目标'' 存在一一对应的关系。然而,对于用户自定义运行级别(2、4)却没有。如需要同样功能,建议你以原有运行级别所对应的 systemd 目标为基础,新建一个{{ic|/etc/systemd/system/''<目标名>.target''}}(可参考{{ic|/usr/lib/systemd/system/graphical.target}}), 然后创建目录{{ic|/etc/systemd/system/<目标名>.wants}},并向其中加入需启用的服务链接(指向{{ic|/ur/lib/systemd/system/}})。
  
=== 目标表 ===
+
=== "SysV 运行级别" 与 "systemd 目标" 对照表 ===
{| border="1"
+
{| class="wikitable"
!SysV 启动级别!!Systemd 目标!!注释
+
!SysV 运行级别!!Systemd 目标!!注释
 
|-
 
|-
 
| 0 || runlevel0.target, poweroff.target || 中断系统(halt)
 
| 0 || runlevel0.target, poweroff.target || 中断系统(halt)
Line 282: Line 282:
 
| 1, s, single || runlevel1.target, rescue.target || 单用户模式
 
| 1, s, single || runlevel1.target, rescue.target || 单用户模式
 
|-
 
|-
| 2, 4 || runlevel2.target, runlevel4.target, multi-user.target || 用户自定义启动级别,通常识别为级别3。
+
| 2, 4 || runlevel2.target, runlevel4.target, multi-user.target || 用户自定义运行级别,通常识别为级别3。
 
|-
 
|-
 
| 3 || runlevel3.target, multi-user.target || 多用户,无图形界面。用户可以通过终端或网络登录。
 
| 3 || runlevel3.target, multi-user.target || 多用户,无图形界面。用户可以通过终端或网络登录。
Line 294: Line 294:
 
|}
 
|}
  
=== 切换启动级别/目标 ===
+
=== 切换当前运行目标 ===
systemd 中,启动级别通过“目标单元”访问。通过如下命令切换:
+
systemd中,运行目标通过“目标单元”访问。通过如下命令切换:
{{bc|# systemctl isolate graphical.target}}
+
# systemctl isolate graphical.target
该命令对下次启动无影响。等价于{{ic|telinit 3}} 或 {{ic|telinit 5}}
+
该命令仅更改当前运行目标,对下次启动无影响。这等价于sysvinit中的 {{ic|telinit 3}} 或 {{ic|telinit 5}} 命令。
  
=== 修改默认启动级别/目标 ===
+
=== 更改开机默认启动目标 ===
开机启动进的目标是 {{ic|default.target}},默认链接到 {{ic|graphical.target}} (大致相当于原来的启动级别5)。可以通过内核参数(grub 菜单 kernel 行)更改默认启动级别:
+
开机启动的目标是 {{ic|default.target}},默认链接到 {{ic|graphical.target}} (大致相当于原来的运行级别5)。
* {{ic|1=systemd.unit=multi-user.target}} (大致相当于级别3)
 
* {{ic|1=systemd.unit=rescue.target}} (大致相当于级别1)
 
  
另一个方法是修改 {{ic|default.target}}。可以通过 {{ic|systemctl}} 修改它:
+
用 ''systemctl'' 检查当前的默认启动目标:
{{bc|# systemctl enable multi-user.target}}
 
  
命令执行情况由 {{ic|systemctl}} 显示:链接 {{ic|/etc/systemd/system/default.target}} 被创建,指向新的默认启动级别。 该方法当且仅当目标配置文件中有以下内容时有效:
+
# systemctl get-default
[Install]
 
Alias=default.target
 
目前,{{ic|multi-user.target}}、{{ic|graphical.target}} 都包含这段内容。
 
  
== 启动桌面环境 ==
+
用 ''systemctl'' 修改{{ic|default.target}}以变更开机默认启动目标:
  
=== 使用登录管理器 ===
+
{{hc|1=$ systemctl set-default multi-user.target|2=
通过启动[[Display Manager (简体中文)|登录管理器]](或称显示管理器),即可进行图形界面登录。目前,Arch 提供了 [[GDM (简体中文)|GDM]]、[[KDM (简体中文)|KDM]]、[[SLiM (简体中文)|SLiM]]、[[XDM (简体中文)|XDM]] 和 [[LXDM (简体中文)|LXDM]] 的 systemd 服务文件。以 KDM 为例,配置开机启动:
+
Removed /etc/systemd/system/default.target.
{{bc|# systemctl enable kdm.service}}
+
Created symlink /etc/systemd/system/default.target -> /usr/lib/systemd/system/graphical.target.}}
  
执行上述命令后,登录管理器应当能正常工作了。如果不是的话,很可能是因为你修改了{{ic|default.target}}。默认情况应当如下:
+
另一方法是向bootloader添加[[Kernel parameters (简体中文)|内核参数]]:
  
{{hc|# ls -l /etc/systemd/system/default.target|/etc/systemd/system/default.target -> /usr/lib/systemd/system/graphical.target}}
+
* {{ic|1=systemd.unit=multi-user.target}} (大致相当于运行级别3)
 +
* {{ic|1=systemd.unit=rescue.target}} (大致相当于运行级别1)
  
删除被修改的 {{ic|default.target}},systemd 会自动使用默认配置(即 {{ic|graphical.target}}):
+
=== 默认目标顺序 ===
 +
 +
Systemd 根据下面顺序选择 {{ic|default.target}}
 +
# 上面的内核参数
 +
# {{ic|/etc/systemd/system/default.target}} 软链接
 +
# {{ic|/usr/lib/systemd/system/default.target}} 软链接
  
{{bc|# rm /etc/systemd/system/default.target}}
+
== 临时文件 ==
 +
{{ic|/usr/lib/tmpfiles.d/}} 和 {{ic|/etc/tmpfiles.d/}} 中的文件描述了 systemd-tmpfiles 如何创建、清理、删除临时文件和目录,这些文件和目录通常存放在 {{ic|/run}} 和 {{ic|/tmp}} 中。配置文件名称为 {{ic|/etc/tmpfiles.d/<program>.conf}}。此处的配置能覆盖 {{ic|/usr/lib/tmpfiles.d/}} 目录中的同名配置。
  
=== 使用服务文件 ===
+
临时文件通常和服务文件同时提供,以生成守护进程需要的文件和目录。例如 [[Samba (简体中文)|Samba]] 服务需要目录 {{ic|/run/samba}} 存在并设置正确的权限位,就象这样:
{{注意|使用此方法的话,用户无法创建 PAM 会话。因此,ConsoleKit(赋予用户关机、操作声音设备等权限的程序)无法正常工作。更好的方案,参见:[[Automatic_login_to_virtual_console#With_systemd]]。}}
+
{{hc|/usr/lib/tmpfiles.d/samba.conf|
 +
D /run/samba 0755 root root
 +
}}
  
这个方法不需要登录管理器,直接启动了X。方法是创建一个新的服务文件:
+
此外,临时文件还可以用来在开机时向特定文件写入某些内容。比如,要禁止系统从USB设备唤醒,利用旧的 {{ic|/etc/rc.local}} 可以用 {{ic|echo USBE > /proc/acpi/wakeup}},而现在可以这么做:
 +
{{hc|/etc/tmpfiles.d/disable-usb-wake.conf|
 +
w /proc/acpi/wakeup - - - - USBE
 +
}}
  
{{hc|/etc/systemd/system/graphical.target.wants/xinit.service|<nowiki>
+
详情参见{{ic|systemd-tmpfiles(8)}} 和 {{man|5|tmpfiles.d}}。
[Unit]
 
Description=Direct login to X
 
After=systemd-user-sessions.service
 
  
[Service]
+
{{注意|该方法不能向 {{ic|/sys}} 中的配置文件添加参数,因为 {{ic|systemd-tmpfiles-setup}} 有可能在相关模块加载前运行。这种情况下,需要首先通过 {{ic|modinfo <模块名>}} 确认需要的参数,然后在 [[Kernel modules (简体中文)#配置模块参数|{{ic|/etc/modprobe.d}} 目录下的配置文件]]中修改配置参数。另外,还可以使用 [[udev (简体中文)#udev 规则|udev 规则]],在设备就绪时设置相应属性。}}
ExecStart=/bin/su <username> -l -c "/bin/bash --login -c xinit"
 
  
[Install]
+
== 定时器 ==
WantedBy=graphical.target
 
</nowiki>}}
 
  
== systemd 日志 ==
+
一个定时器是一个以 {{ic|.timer}} 为结尾的单元配置文件并包含由 {{ic|systemd}} 控制和监督的信息。[[systemd/Timers (简体中文)]]
自版本 38 起,systemd 提供了自己日志系统(logging system),称为 journal(还是日志的意思)。
 
  
使用 systemd 日志,无需额外安装日志服务(syslog)。读取日志的命令:
+
{{注意|定时器很大程度上可取代 {{ic|cron}}。[[systemd/Timers (简体中文)#替代 cron]]}}
{{bc|# journalctl}}
 
日志记录在虚拟文件系统内({{ic|/run/systemd/journal}}),所以重启后就会消失。要保留的话,需手动创建目录 {{ic|/var/log/journal/}}:
 
{{bc|# mkdir /var/log/journal/}}
 
  
=== 过滤输出 ===
+
== 挂载 ==
  
{{ic|journalctl}}可以根据特殊字段过滤输出,例如:
+
因为 systemd 也负责按 {{ic|/etc/fstab}} 挂载目录。在系统启动和重新加载系统管理器时,{{man|8|systemd-fstab-generator}} 会将 {{ic|/etc/fstab}} 中的配置转化为 systemd 单元。
  
显示给定可执行文件的所有消息:
+
''systemd'' 扩展了 [[fstab]] 的传统功能,提供了额外的挂载选项。例如可以确保一个挂载仅在网络已经连接时进行,或者仅当另外一个分区已挂载时再挂载。这些选项通常以 {{ic|x-systemd.}} 开头,{{man|5|systemd.mount|FSTAB}} 中包含了完整说明。
{{bc|# journalctl /usr/lib/systemd/systemd}}
 
  
显示指定过程的所有消息:
+
''automounting'' 也是一个例子,可以在使用时,而不是启动时挂载分区,详情请参考 [[fstab#Automount with systemd]]。
{{bc|1=# journalctl _PID=1}}
 
  
显示指定单元的所有消息:
+
=== GPT 分区自动挂载 ===
{{bc|1=# journalctl _SYSTEMD_UNIT=netcfg.service}}
 
  
详情参阅{{ic|man journalctl}}{{ic|systemd.journal-fields}}
+
在 [[GPT]] 分区磁盘系统上,{{man|8|systemd-gpt-auto-generator}} 会按照 [https://www.freedesktop.org/wiki/Specifications/DiscoverablePartitionsSpec/ 可探测分区规范] 进行挂载。可以在 {{ic|fstab}} 中忽略。
  
=== 日志大小限制 ===
+
要禁用自动挂载,请修改分区的 [[Wikipedia:GUID Partition Table#Partition type GUIDs|类型 GUID]] 或设置分区属性 63 位 "不自动挂载",详情参考 [[gdisk#Prevent GPT partition automounting]]。
  
如果按上面的操作保留日志的话,默认日志最大限制为所在文件系统容量的 10%,即:如果 {{ic|/var/log/journal}} 储存在 50GiB 的根分区中,那么日志最多存储 5GiB 数据。可以修改 {{ic|/etc/systemd/journald.conf}} 中的 {{ic|SystemMaxUse}} 来指定该最大限制。如限制日志最大 50MiB:
+
== Tips and tricks ==
{{bc|1=SystemMaxUse=50M}}
 
详情参见 {{ic|man journald.conf}}.
 
  
=== 配合传统日志服务(syslog) ===
+
=== Running services after the network is up ===
systemd 提供了 socket {{ic|/run/systemd/journal/syslog}},以兼容传统日志服务。所有系统信息都会被传入。要使传统日志服务工作,需要让服务链接该 socket,而非 {{ic|/dev/log}}(http://lwn.net/Articles/474968/ 官方说明)。以 Arch 原先默认的 syslog-ng 服务为例,修改 {{ic|/etc/syslog-ng/syslog-ng.conf}} 的 source 部分:
 
{{bc|<nowiki>
 
source src {
 
    unix-dgram("/run/systemd/journal/syslog");
 
    internal();
 
    file("/proc/kmsg");
 
};</nowiki>}}
 
  
设置开机启动 syslog-ng:
+
To delay a service after the network is up, include the following dependencies in the ''.service'' file:
{{bc|# systemctl enable syslog-ng.service}}
 
  
== 网络 ==
+
{{hc|/etc/systemd/system/''foo''.service|2=
=== DHCP 动态获取 IP ===
+
[Unit]
如果使用 DHCP 动态获取 IP,可以使用 {{Pkg|dhcpcd}} 软件包提供的 {{ic|dhcpcd@.service}}。例如,为 {{ic|eth0}} 启用 DHCP:
+
...
# systemctl start dhcpcd@eth0.service
+
'''Wants=network-online.target'''
 +
'''After=network-online.target'''
 +
...
 +
}}
  
设置开机自动配置:
+
The network wait service of the particular application that manages the network, must also be enabled so that {{ic|network-online.target}} properly reflects the network status.
  # systemctl enable dhcpcd@eth0.service
 
  
=== 其他配置方式 ===
+
* For the ones using [[NetworkManager]], [[enable]] {{ic|NetworkManager-wait-online.service}}.
对于静态IP、无线网络或其他上网方式,建议使用 [[netcfg (简体中文)|netcfg]] [[NetworkManager (简体中文)|NetworkManager]],两者都提供了 systemd 服务文件。
+
* If using [[systemd-networkd]], {{ic|systemd-networkd-wait-online.service}} is by default enabled automatically whenever {{ic|systemd-networkd.service}} has been enabled; check this is the case with {{ic|systemctl is-enabled systemd-networkd-wait-online.service}}, there is no other action needed.
  
{{Note|如果使用[[NetworkManager]],启用{{ic|NetworkManager-wait-online.service}} 服务可以让单元依赖于{{ic|network.target}}等待网络连接建立才启动。}}
+
For more detailed explanations see [https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/ Running services after the network is up] in the systemd wiki.
  
如果使用静态IP,又不想用额外的工具,可以手动创建一个[[Systemd/Services#Network|服务]]。
+
=== Enable installed units by default ===
 +
 +
{{Expansion|How does it work with instantiated units?}}
  
== Arch 整合 ==
+
Arch Linux ships with {{ic|/usr/lib/systemd/system-preset/99-default.preset}} containing {{ic|disable *}}. This causes ''systemctl preset'' to disable all units by default, such that when a new package is installed, the user must manually enable the unit.
  
=== Initscripts 模拟 ===
+
If this behavior is not desired, simply create a symlink from {{ic|/etc/systemd/system-preset/99-default.preset}} to {{ic|/dev/null}} in order to override the configuration file. This will cause ''systemctl preset'' to enable all units that get installed—regardless of unit type—unless specified in another file in one ''systemctl preset'''s configuration directories. User units are not affected. See the manpage for {{ic|systemd.preset}} for more information.
  
{{Pkg|initscripts}} 软件包提供了 systemd 和 Arch 传统配置的整合。这种模拟方便用户向 systemd 的转换。{{ic|/etc/inittab}} 彻底废弃。
+
{{Note|Enabling all units by default may cause problems with packages that contain two or more mutually exclusive units. ''systemctl preset'' is designed to be used by distributions and spins or system administrators. In the case where two conflicting units would be enabled, you should explicitly specify which one is to be disabled in a preset configuration file as specified in the manpage for {{ic|systemd.preset}}.}}
  
If you disabled {{keypress|Ctrl+Alt+Del}} to reboot in {{ic|/etc/inittab}}, you will have to reconfigure this setting for systemd by running {{ic|systemctl mask ctrl-alt-del.target}} as root.
+
=== Sandboxing application environments ===
  
=== rc.conf ===
+
A unit file can be created as a sandbox to isolate applications and their processes within a hardened virtual environment. systemd leverages [[wikipedia:Linux_namespaces|namespaces]], white-/blacklisting of [[Capabilities]], and [[control groups]] to container processes through an extensive [https://www.freedesktop.org/software/systemd/man/systemd.exec.html execution environment configuration].
{{ic|/etc/rc.conf}} 中的部分设置仍然可用。不过还是使用[[#原生 systemd 配置文件|原生 systemd 配置]]代替为好。
 
  
支持的变量:
+
The enhancement of an existing systemd unit file with application sandboxing typically requires trial-and-error tests accompanied by the generous use of {{Pkg|strace}}, [[wikipedia:Standard_streams#Standard_error_.28stderr.29|stderr]] and [https://www.freedesktop.org/software/systemd/man/journalctl.html journalctl] error logging and output facilities. You may want to first search upstream documentation for already done tests to base trials on.
* LOCALE
 
* KEYMAP
 
* CONSOLEFONT
 
* CONSOLEMAP
 
* HOSTNAME
 
* DAEMONS
 
  
不支持的变量,以及替代的 systemd 设置:
+
Some examples on how sandboxing with systemd can be deployed:
* TIMEZONE:自行建立软链接 {{Ic|/etc/localtime}},指向对应的时区文件(比如 {{Ic|/usr/share/zoneinfo/Asia/Shanghai}})。
 
* HARDWARECLOCK:参见[[#硬件时钟]]。
 
* USELVM:使用 {{Pkg|lvm2}} 提供的 {{ic|lvm.service}} 代替。
 
* USECOLOR
 
* MODULES
 
  
=== 完全切换到原生 systemd ===
+
* {{Ic|CapabilityBoundingSet}} defines a whitelisted set of allowed capabilities, but may also be used to blacklist a specific capability for a unit.
{{注意|这是推荐的方法,这样系统不再需要{{ic|rc.conf}},而是使用原生 systemd 配置文件。}}
+
** The {{Ic|CAP_SYS_ADM}} capability, for example, which should be one of the [https://lwn.net/Articles/486306/ goals of a secure sandbox]: {{ic|1=CapabilityBoundingSet=~ CAP_SYS_ADM}}
  
按照 Systemd 原生配置文件的介绍,将{{ic|/etc/rc.conf}}中的段落替换为相应的配置文件:
+
== 疑难解答 ==
 
+
=== 寻找错误 ===
{| class="wikitable"
 
|-
 
! scope="col"| 配置内容
 
! scope="col"| 配置文件
 
! scope="col"| 老{{ic|/etc/rc.conf}}段落
 
|-
 
| align="center"|Hostname
 
| align="left"|{{ic|/etc/hostname}}
 
{{ic|/etc/hosts}}
 
| align="center"|{{ic|NETWORKING}}
 
|-
 
| align="center"|终端字体和键盘映射
 
| align="left"|{{ic|/etc/vconsole.conf}}
 
| align="center"|{{ic|LOCALIZATION}}
 
|-
 
| align="center"|Locale
 
| align="left"|{{ic|/etc/locale.conf}}
 
{{ic|/etc/locale.gen}}
 
| align="center"|{{ic|LOCALIZATION}}
 
|-
 
| align="center"|时区
 
| align="left"|{{ic|/etc/timezone}}
 
{{ic|/etc/localtime}}
 
| align="center"|{{ic|LOCALIZATION}}
 
|-
 
| align="center"|硬件时钟
 
| align="left"|{{ic|/etc/adjtime}}
 
| align="center"|{{ic|LOCALIZATION}}
 
|-
 
| align="center"|内核模块
 
| align="left"|{{ic|/etc/modules-load.d/}}
 
| align="center"|{{ic|HARDWARE}}
 
|-
 
| align="center"|Daemons
 
| align="left"|{{ic|/etc/rc.conf}}
 
| align="center"|{{ic|DAEMONS}}
 
|-
 
| align="center"|有线网络
 
| align="left"|{{ic|/etc/rc.conf}}
 
| align="center"|{{ic|NETWORKING}}
 
|}
 
因为历史原因,{{ic|/etc/rc.conf}}中的'''DAEMONS'''段落依然与 systemd 兼容,可以用来在开机时启动服务。你可以选择删除{{ic|/etc/rc.conf}}文件并完全通过 systemd 启动服务。对每个 '''DAEMONS''' 中的服务名,执行:
 
# systemctl enable <service_name>.service
 
{{Tip|服务的对应列表位于 [[Daemon#List_of_Daemons|这里]]。}}
 
 
 
如果服务名 {{ic|<service_name>.service}} 不存在:
 
* systemd 可能还没有提供相应的服务文件,这时只能通过{{ic|rc.conf}}启动服务。
 
* systemd 中服务名可能有变化:
 
** {{ic|cronie.service}} 替代了{{ic|crond}}
 
** {{ic|alsa-store.service}} 和 {{ic|alsa-restore.service}} 替代了 {{ic|alsa}}。
 
** {{ic|network}}被几个服务文件替代,详情参阅网络部分。
 
* systemd 会自动处理这些服务的启动顺序。
 
* 有些服务不需要用户明确启用,例如只要安装了{{ic|dbus-core}},{{ic|dbus.service}}就会自动启动。可以通过{{ic|systemctl}}命令检查服务的启动状态。
 
  
{{Tip|可以检查软件包提供的文件,看看服务使用哪个启动脚本。例如:
+
这个例子中的失败的服务是 {{ic|systemd-modules-load}} :
$ pacman -Ql cronie
 
[...]
 
cronie /etc/rc.d/crond                            #<-- daemon initscript listed in the DAEMONS array (unused in a "pure" systemd configuration)
 
[...]
 
cronie /usr/lib/systemd/system/cronie.service    #<-- corresponding systemd daemon service
 
[...]
 
}}
 
  
==Writing custom .service files==
+
'''1.''' 通过 ''systemd'' 寻找启动失败的服务:
===Handling dependencies===
 
With systemd dependencies can be resolved by designing the unit files correctly. The most typical case is that the unit {{ic|A}} requires the unit {{ic|B}} to be running before {{ic|A}} is started. In that case add {{ic|1=Requires=B}} and {{ic|1=After=B}} to the {{ic|[Unit]}} section of {{ic|A}}. If the dependency is optional, add {{ic|1=Wants=B}} and {{ic|1=After=B}} instead. Note that {{ic|1=Wants=}} and {{ic|1=Requires=}} do not imply {{ic|1=After=}}, meaning that if {{ic|1=After=}} is not specified, the two units will be started in parallel.
 
  
Dependencies are typically placed on services and not on targets. For example, {{ic|network.target}} is pulled in by whatever service configures your network interfaces, therefore ordering your custom unit after it is sufficient since {{ic|network.target}} is started anyway.
+
{{hc|1=$ systemctl --state=failed|2=
 +
systemd-modules-load.service   loaded '''failed failed'''  Load Kernel Modules}}
  
===Type===
+
或者使用 ''systemd'' 消息:
There are several different start-up types to consider when writing a custom service file. This is set with the {{ic|1=Type=}} parameter in the {{ic|[Service]}} section. See {{ic|man systemd.service}} for a more detailed explanation.
+
$ journalctl -fp err
* {{ic|1=Type=simple}}: systemd considers the daemon to be started up immediately. The process must not fork. Do not use this type if other services need to be ordered on this service, unless it is socket activated.
 
* {{ic|1=Type=forking}}: systemd considers the daemon started up once the process forks and the parent has exited. For classic daemons use this type unless you know that it is not necessary, as most daemons use double-forking to signal that they are ready. You should specify {{ic|1=PIDFile=}} as well so systemd can keep track of the main process.
 
* {{ic|1=Type=oneshot}}: This is useful for scripts that do a single job and then exit. You may want to set {{ic|1=RemainAfterExit=}} as well so that systemd still considers the service as active after the process has exited.
 
* {{ic|1=Type=notify}}: Identical to {{ic|1=Type=simple}}, but with the stipulation that the daemon will send a signal to systemd when it is ready. This requires systemd-specific code provided by {{ic|libsystemd-daemon.so}}.
 
* {{ic|1=Type=dbus}}: The daemon is considered ready when the specified {{ic|BusName}} appears on DBus's system bus.
 
  
===Replacing provided unit files===
+
'''2.''' 我们发现了启动失败的 {{ic|systemd-modules-load}} 服务. 我们想知道更多信息:
The unit files in {{ic|/etc/systemd/system/}} take precedence over the ones in {{ic|/usr/lib/systemd/system/}}.
 
To make your own version of a unit (which will not be destroyed by an upgrade), copy the old unit file from {{ic|/usr/lib/}} to {{ic|/etc/}} and make your changes there. Alternatively you can use {{ic|.include}} to parse an existing service file and then override or add new options. For example, if you simply want to add an additional dependency to a service file, you may use:
 
{{hc|/etc/systemd/system/<service-name>.service|
 
<nowiki>
 
.include /usr/lib/systemd/system/<service-name>.service
 
  
[Unit]
+
{{hc|$ systemctl status systemd-modules-load|2=
Requires=<new dependency>
+
systemd-modules-load.service - Load Kernel Modules
After=<new dependency>
+
  Loaded: loaded (/usr/lib/systemd/system/systemd-modules-load.service; static)
</nowiki>}}
+
  Active: '''failed''' (Result: exit-code) since So 2013-08-25 11:48:13 CEST; 32s ago
Then run the following for your changes to take effect:
+
    Docs: man:systemd-modules-load.service(8).
# systemctl reenable <unit>
+
          man:modules-load.d(5)
# systemctl restart <unit>
+
  Process: '''15630''' ExecStart=/usr/lib/systemd/systemd-modules-load ('''code=exited, status=1/FAILURE''')
{{Tip|You can use {{ic|systemd-delta}} to see which unit files have been overridden and what exactly has been changed.}}
+
}}
  
===Syntax highlighting for systemd unit files within Vim===
+
如果没列出 {{ic|Process ID}}, 通过 {{ic|systemctl}} 重新启动失败的服务 ( 例如 {{ic|systemctl restart systemd-modules-load}} )
Syntax highlighting for systemd unit files within [[Vim]] can be enabled by installing {{AUR|vim-systemd}} from the [[Arch User Repository|AUR]].
 
  
== FAQ ==
+
'''3.''' 现在得到了 PID ,你就可以进一步探查错误的详细信息了.通过下列的命令收集日志,PID 参数是你刚刚得到的 {{ic|Process ID}} (例如 15630):
最新的已知问题,参见:[http://cgit.freedesktop.org/systemd/systemd/tree/TODO TODO]。
 
  
{{FAQ
+
{{hc|1=$ journalctl -b _PID=15630|2=
|question=控制台字体很难看,怎么办?
+
-- Logs begin at Sa 2013-05-25 10:31:12 CEST, end at So 2013-08-25 11:51:17 CEST. --
|answer=如果 {{ic|/etc/vconsole.conf}}(以及备用的 {{ic|/etc/rc.conf}}) 中没有设置控制台字体,那么会使用一个支持很多字符集的标准字体。自己设置一个好看的字体吧。}}
+
Aug 25 11:48:13 mypc systemd-modules-load[15630]: '''Failed to find module 'blacklist usblp''''
 
+
Aug 25 11:48:13 mypc systemd-modules-load[15630]: '''Failed to find module 'install usblp /bin/false''''
{{FAQ
+
}}
|question=为什么控制台上会显示日志信息?
 
|answer=请自行设置内核日志等级(loglevel)。以前,{{ic|/etc/rc.sysinit}} 帮我们把 dmesg 的日志等级设置为 {{ic|3}},是比较合适的。在启动引导器中添加内核参数 {{ic|1=loglevel=3}} 或 {{ic|quiet}} 即可。}}
 
 
 
{{FAQ
 
|question=如何修改启用的可登陆的 tty 控制台(getty)数量?
 
|answer=添加新的 getty:
 
 
 
在 {{ic|/etc/systemd/system/getty.target.wants/}} 添加新的软链接即可:
 
 
 
{{bc|<nowiki># ln -sf /usr/lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@tty9.service
 
# systemctl daemon-reload
 
# systemctl start getty@tty9.service</nowiki>}}
 
 
 
移除 getty:
 
 
 
从 {{ic|/etc/systemd/system/getty.target.wants/}} 删除对应的软链接即可:
 
 
 
{{bc|<nowiki># 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</nowiki>}}
 
 
 
systemd 不使用 {{ic|/etc/inittab}} 文件。
 
 
 
{{注意|自 systemd 版本 30,系统默认只开启一个 getty。只有切换到别的 tty 时,才会开启新的 getty(socket 激活式)。但仍可使用上述方法强制添加新的 getty。}}}}
 
  
{{FAQ
+
'''4.''' 我们发现有些内核模块的配置文件不正确,因此在  {{ic|/etc/modules-load.d/}} 中检查一下:
|question=怎样输出更详细的开机信息?
 
|answer=如果内核信息输出后就什么信息都不输出了,很可能是因为你在内核参数中添加了 {{ic|quiet}}。删除即可,然后你就可以看到一列列绿色的 [ OK ] 和红色的 [ FAILED ]了。
 
  
所有信息都记录在系统日志,可以通过 {{ic|$ systemctl}} 查看系统状态,通过 {{ic|journalctl}} 查看日志。
+
{{hc|$ ls -Al /etc/modules-load.d/|
 +
...
 +
-rw-r--r--  1 root root    79  1. Dez 2012  blacklist.conf
 +
-rw-r--r--  1 root root    1  2. Mär 14:30 encrypt.conf
 +
-rw-r--r--  1 root root    3  5. Dez 2012  printing.conf
 +
-rw-r--r--  1 root root    6 14. Jul 11:01 realtek.conf
 +
-rw-r--r--  1 root root    65  2. Jun 23:01 virtualbox.conf
 +
...
 
}}
 
}}
  
{{FAQ
+
'''5.''' 错误消息 {{ic|Failed to find module 'blacklist usblp'}} 也许和  {{ic|blacklist.conf}} 相关. 让我们注释掉第三步发现的错误的选项:
|question=开机后控制台信息会被清空,如何避免?
 
|answer=自己写一个 getty@tty1.service 文件
 
  
{{ic|/usr/lib/systemd/system/getty@.service}} 复制到 {{ic|/etc/systemd/system/getty.target.wants/getty@tty1.service}},编辑该文件:
+
{{hc|/etc/modules-load.d/blacklist.conf|
* 在 {{ic|ExecStart}} 行的 {{ic|agetty}} 后添加 {{ic|--noclear}}
+
'''#''' blacklist usblp
* 修改 {{ic|TTYVTDisallocate}} 为 {{ic|no}}
+
'''#''' install usblp /bin/false
 
}}
 
}}
  
{{FAQ
+
'''6.''' 最后重新启动 {{ic|systemd-modules-load}} 服务:
|question=我不用官方内核,内核版本和编译参数有什么要注意的吗?
 
|answer=systemd 不支持 2.6.39 版本之前的内核。
 
  
这里有一些必须/推荐的编译设置,但并不全:
+
# systemctl start systemd-modules-load
  
{{bc|<nowiki>
+
如果服务成功启动,不会有任何输出.如果你还是遇到了错误,回到步骤三,获得新的 PID 来跟踪日志并解决错误.
CONFIG_AUDIT=y (推荐)
 
CONFIG_AUDIT_LOGINUID_IMMUTABLE=y (不必要,会破坏 sysvinit 兼容性)
 
CONFIG_CGROUPS=y
 
CONFIG_IPV6=[y|m] (强烈推荐)
 
CONFIG_UEVENT_HELPER_PATH="" (如果不使用 initramfs 的话)
 
CONFIG_DEVTMPFS=y
 
CONFIG_DEVTMPFS_MOUNT=y (推荐,如果不使用 initramfs 的话)
 
CONFIG_RTC_DRV_CMOS=y (强烈推荐)
 
CONFIG_FANOTIFY=y (readahead 需要)
 
CONFIG_AUTOFS4_FS=[y|m]
 
CONFIG_TMPFS_POSIX_ACL=y (推荐,如果使用 pam_systemd.so 的话)
 
</nowiki>}}}}
 
  
{{FAQ
+
可以像这样确认服务成功启动:
|question=怎样知道一个单元依赖哪些单元?
 
|answer=例如,你可能想搞明白目标单元 {{ic|multi-user.target}} 究竟启用了哪些服务,那么以下命令即可:
 
{{hc|$ systemctl show -p "Wants" multi-user.target|2=Wants=ntpd.service cronie.service cpufreq.service psd.service syslog-ng.service remote-fs.target NetworkManager.service rc-local.service goagent.service dbus.service systemd-ask-password-wall.path systemd-logind.service getty.target systemd-user-sessions.service systemd-update-utmp-runlevel.service}}
 
  
除了 {{ic|Wants}},还可以查看各种形式的依赖和被依赖信息:{{ic|WantedBy}}、{{ic|Requires}}、{{ic|RequiredBy}}、{{ic|Conflicts}}、{{ic|ConflictedBy}}、{{ic|Before}}、{{ic|After}}。}}
+
{{hc|$ systemctl status systemd-modules-load|2=
 +
systemd-modules-load.service - Load Kernel Modules
 +
  Loaded: '''loaded''' (/usr/lib/systemd/system/systemd-modules-load.service; static)
 +
  Active: '''active (exited)''' since So 2013-08-25 12:22:31 CEST; 34s ago
 +
    Docs: man:systemd-modules-load.service(8)
 +
          man:modules-load.d(5)
 +
Process: 19005 ExecStart=/usr/lib/systemd/systemd-modules-load (code=exited, status=0/SUCCESS)
 +
Aug 25 12:22:31 mypc systemd[1]: '''Started Load Kernel Modules'''.
 +
}}  
  
{{FAQ
+
=== 诊断启动问题 ===
|question=电脑关闭了但电源没有断。
 
|answer=使用
 
$ systemctl poweroff
 
而不是 systemctl halt.}}
 
  
{{FAQ
+
使用如下内核参数引导:
|question=After migrating to systemd, why won't my fakeRAID mount?
+
{{ic|<nowiki>systemd.log_level=debug systemd.log_target=kmsg log_buf_len=1M</nowiki>}}
|answer=Be sure you use {{bc|# systemctl enable dmraid.service}}
 
}}
 
  
{{FAQ
+
更多有关调试的信息,参见[https://freedesktop.org/wiki/Software/systemd/Debugging 该文]
|question=How can I make a script start during the boot process?
 
|answer=Create a new file in {{ic|/etc/systemd/system}} (e.g. ''myscript''.service) and add the following contents:
 
{{bc|<nowiki>
 
[Unit]
 
Description=My script
 
  
[Service]
+
=== 诊断一个服务 ===
ExecStart=/usr/bin/my-script
 
  
[Install]
+
如果某个 ''systemd'' 服务的工作状况不合预期,希望调试的话,设置 {{ic|SYSTEMD_LOG_LEVEL}} [[environment variable|环境变量]] 为 {{ic|debug}} . 例如以调试模式运行 ''systemd-networkd'' 服务:
WantedBy=multi-user.target
 
</nowiki>}}
 
Then
 
{{bc|# systemctl enable ''myscript''.service}}
 
This example assumes you want your script to start up when the target multi-user is launched.
 
}}
 
  
== 优化 ==
+
在此服务的配置文件片段中加入:
=== 启动过程分析 ===
 
systemd 提供了一个分析启动过程的工具 —— {{ic|systemd-analyze}}。可以用它看看哪些单元拖慢了开机过程,并据此进行优化。安装 {{Pkg|python2-dbus}}、{{Pkg|python2-cairo}} 软件包后该工具才能工作。
 
  
查看开机过程在内核/用户空间消耗的时间:
+
[Service]
  $ systemd-analyze
+
  Environment=SYSTEMD_LOG_LEVEL=debug
{{技巧|如果在 {{ic|/etc/mkinitcpio.conf}} 的 {{ic|HOOKS}} 数组添加 {{ic|timestamp}},并重新生成启动内存镜像(initramfs),{{ic|systemd-analyze}} 还可以显示处理该启动镜像花费的时间。}}
 
  
按照耗费时间顺序,输出启动每个单元耗费的时间:
+
或者等价的,临时编辑系统单元文件,例如:
$ systemd-analyze blame
 
  
生成类似于 [[Bootchart (简体中文)|bootchart]] 的开机过程图表:
+
# SYSTEMD_LOG_LEVEL=debug /lib/systemd/systemd-networkd
$ systemd-analyze plot > plot.svg
 
  
==== 【不建议】使用 bootchart ====
+
[[restart|重启]] ''systemd-networkd'' 服务,用 {{ic|--follow}} 选项检查日志。
由于没有办法在内核参数设置两个 init,所以不能使用源里的 bootchart。不过,[[AUR (简体中文)|AUR]] 软件包 {{AUR|bootchart2}} 提供了一个的 systemd 服务,安装后启用即可:
 
{{bc|# systemctl enable bootchart.service}}
 
详情参阅 [https://github.com/mmeeks/bootchart bootchart 文档]。
 
  
=== shell 短命令 ===
+
=== 关机/重启十分缓慢 ===
systemd 的管理命令都死长死长的,可以向 {{ic|~/.bashrc}} 添加下面的内容,简化命令以保护键盘:
 
{{bc|# 简化systemd命令,例如sudo systemctl stop xxx.service 简化后变成 0.stop xxx
 
if ! systemd-notify --booted;
 
then  # 兼容不用 systemd 的情况
 
    0.start() {
 
        sudo rc.d start $1
 
    }
 
  
    0.restart() {
+
如果关机特别慢(甚至跟死机了一样),很可能是某个拒不退出的服务在作怪。systemd 会等待一段时间,然后再尝试杀死它。请阅读[https://freedesktop.org/wiki/Software/systemd/Debugging#Shutdown_Completes_Eventually 这篇文章],确认你是否是该问题受害者。
        sudo rc.d restart $1
 
    }
 
  
    0.stop() {
+
=== 短时进程无日志记录 ===
        sudo rc.d stop $1
 
    }
 
else
 
# start systemd service
 
# 运行一个守护进程
 
    0.start() {
 
        sudo systemctl start $1.service
 
    }
 
# restart systemd service
 
# 重启一个守护进程
 
    0.restart() {
 
        sudo systemctl restart $1.service
 
    }
 
# stop systemd service
 
# 关闭一个守护进程
 
    0.stop() {
 
        sudo systemctl stop $1.service
 
    }
 
# enable systemd service
 
# 启用一个守护进程
 
    0.enable() {
 
        sudo systemctl enable $1.service
 
    }
 
# disable a systemd service
 
# 停用一个守护进程
 
    0.disable() {
 
        sudo systemctl disable $1.service
 
    }
 
# show the status of a service
 
# 查看一个守护进程状态
 
    0.status() {
 
        sudo systemctl status $1.service
 
    }
 
# reload a service configuration
 
# 重新加载一个守护进程的配置文件
 
    0.reload() {
 
        sudo systemctl reload $1.service
 
    }
 
# list all running service
 
# 列出所有运行中的守护进程
 
    0.list() {
 
        sudo systemctl
 
    }
 
# list all failed service
 
# 列出所有运行失败的守护进程
 
    0.failed () {
 
        sudo systemctl --failed
 
    }
 
# list all systemd available unit files
 
# 列出所有可用的进程文件
 
    0.list-files() {
 
        sudo systemctl list-unit-files
 
    }
 
# check the log
 
# 查看系统日志
 
    0.log() {
 
        sudo journalctl
 
    }
 
# show wants
 
# 列出某个目标所需要的进程
 
    0.wants() {
 
        sudo systemctl show -p "Wants" $1.target
 
    }
 
# analyze the system
 
# 查看启动进程所耗时间
 
    0.analyze() {
 
        systemd-analyze
 
    }
 
fi
 
}}
 
  
=== 精简输出信息 ===
+
{{ic|journalctl -u foounit.service}} 没有显示某个短时进程的任何输出,那么改用 PID 试试。例如,若 {{ic|systemd-modules-load.service}} 执行失败,那么先用 {{ic|systemctl status systemd-modules-load}} 查询其 PID(比如是123),然后检索该 PID 相关的日志 {{ic|journalctl -b _PID&#61;123}}。运行时进程的日志元数据(诸如 _SYSTEMD_UNIT 和 _COMM)被乱序收集在 {{ic|/proc}} 目录。要修复该问题,必须修改内核,使其通过套接字连接来提供上述数据,该过程类似于 SCM_CREDENTIALS。
修改启动加载器内核参数中的 {{ic|verbose}} {{ic|quiet}} 即可。对于某些用户,特别是 SSD 用户,TTY 的龟速实际上成为了性能瓶颈,精简输出信息实际上有利于提高性能。
 
  
=== 尽早启动单元 ===
+
=== 禁止在程序崩溃时转储内存 ===
systemd 的一个重要特性是 dbus 总线式和 socket 式任务激活,即服务仅在第一次被使用时才启动,通常来说这样是很有好处的。不过,某些服务(比如 console-kit)开机时肯定是要启动的,早点启动反而节约时间(只是有些服务支持这样做):
+
要使用老的内核转储,创建下面文件:
 +
{{hc|/etc/sysctl.d/49-coredump.conf|2=<nowiki>
 +
kernel.core_pattern = core
 +
kernel.core_uses_pid = 0</nowiki>}}
  
{{bc|# systemctl enable console-kit-daemon.service}}
+
然后运行:
 +
# /usr/lib/systemd/systemd-sysctl
  
这样 systemd 就会尽早启动 console-kit,而不必等待激活。
+
同样可能需要执行“unlimit”设置文件大小:
 +
$ ulimit -c unlimited
  
=== 自动挂载 ===
+
更多信息请参阅 [https://www.freedesktop.org/software/systemd/man/sysctl.d.html sysctl.d] 和 [https://www.kernel.org/doc/Documentation/sysctl/kernel.txt /proc/sys/kernel 文档]。
默认情况下,多数服务的启动必须等待磁盘检查和挂载所有文件系统。如果你的 {{ic|/home}} 分区很大,最好还是让不需要这个分区的服务先启动,{{ic|/home}} 在一边慢慢检查。添加下列内容到 {{ic|/etc/fstab}} 对应行的 options 列即可:
 
  
noauto,x-systemd.automount
+
=== 启动的时间太长 ===
  
这样,只有 {{ic|/home}} 第一次被访问时才会检查和挂载。内核会负责缓冲所有对 {{ic|/home}} 的 I/O 操作,直到分区就绪。
+
不少用户用了 {{ic|systemd-analyze}} 命令以后报告启动的时间比预计的要长,通常会说 {{ic|systemd-analyze}} 分析结果表示 [[NetworkManager]] 占据了太多的启动的时间.
  
如果使用带有密码文件的加密文件系统,也可以在 {{ic|/etc/crypttab}} 中的相应项添加 {{ic|noauto}} 参数。这样,systemd 不会在开机时就挂载加密文件系统,而要等待首次访问后再使用特定密码文件挂载。如果使用加密的 RAID 设备,这样或许可以节约几秒开机时间。例如:
+
有些用户的问题是 {{ic|/var/log/journal}} 文件夹似乎过大.这也许也会对像{{ic|systemctl status}} {{ic|journalctl}} 的命令有影响.一种解决方案是删除其中的文件 (但最好将它们备份到某处) 然后限制日志文件的大小.
{{hc|/etc/crypttab|data /dev/md0 /root/key noauto}}
 
  
=== 启动速度优化 ===
+
=== systemd-tmpfiles-setup.service 在启动时启动失败 ===
systemd 自己实现了一个 readahead,可以用来提高开机效率。不过,效果会因内核版本和硬件情况而不同(极端的还会变慢)。开启 readahead:
+
从 systemd 219 开始, {{ic|/usr/lib/tmpfiles.d/systemd.conf}} 指定 {{ic|/var/log/journal}} 的 ACL 属性和目录, 因此日志所在的文件系统上要启用ACL.
  
{{bc|<nowiki># systemctl enable systemd-readahead-collect.service systemd-readahead-replay.service</nowiki>}}
+
参阅 [[Access Control Lists#Enabling ACL]] 获得如何包含 {{ic|/var/log/journal}} 启动 ACL 的详细信息.
  
要知道,readahead 的超级牛力只有在重启几次后才会显现。
+
=== 启动时显示的 systemd 版本和安装版本不一致 ===
  
=== 用户会话 ===
+
需要 [[Mkinitcpio#Image_creation_and_activation|重新生成 initramfs]]。
systemd 可以将用户会话划分进不同的 cgroups。添加 {{ic|session optional pam_systemd.so}} 到 {{ic|/etc/pam.d/}} 中相关文件(例如,控制 tty 登录的 {{ic|login}},控制远程登录的 {{ic|sshd}},控制需要密码的 KDM 登录的 {{ic|kde}},控制 KDM 自动登录的 {{ic|kde-np}})。
 
  
操作前:
+
{{提示|1=可以使用 pacman 钩子在更新 {{pkg|systemd}}时重新生成 initramfs。参考 [https://bbs.archlinux.org/viewtopic.php?id=215411 这个帖子] 和 [[Pacman#Hooks]].}}
{{hc|$ systemd-cgls systemd:/system/getty@.service|
 
systemd:/system/getty@.service:
 
├ tty5
 
│ └ 904 /sbin/agetty tty5 38400
 
├ tty2
 
│ ├ 13312 /bin/login --
 
│ └ 15765 -zsh
 
[]}}
 
操作后:
 
{{hc|$ systemd-cgls systemd:/user/example/|
 
systemd:/user/example/:
 
├ 4
 
│ ├  902 /bin/login --
 
│ └ 16016 -zsh
 
[…]}}
 
  
进一步,可以完全用 systemd 替代 [[ConsoleKit (简体中文)|ConsoleKit]]。不过,必须手动从 [[ABS (简体中文)|ABS]] 重新编译 {{Pkg|polkit}},添加 systemd 支持({{ic|--enable-systemd}})。这样,即使不用 ConsoleKit,用户也有自动挂载U盘之类的权限了。DBus 自 1.6.0 版本就支持 systemd,无需从 git 重新编译。
+
=== 禁用远程机器的 emergency 模式 ===
  
== 疑难解答 ==
+
如果远程机器位于云主机,emergency 模式会导致系统无法远程连接,可以通过下面方式禁用紧急模式:
=== 关机/重启十分缓慢 ===
 
如果关机特别慢(甚至跟死机了一样),很可能是某个拒不退出的服务在作怪。systemd 会等待一段时间,然后再杀死它。
 
请阅读 Fedora wiki 上的[http://fedoraproject.org/wiki/How_to_debug_Systemd_problems#Diagnosing_shutdown_problems 文章],确认你是否是该问题受害者。
 
  
==== SLiM 和 xfce-session ====
+
# systemctl mask emergency.service
目前,已知会导致关机缓慢的一种情况是,Xfce 配合 SLiM:使用 xfce-session 关机/重启会导致 slim.service 卡死,直到半分钟后 systemd 杀死它。
+
# systemctl mask emergency.target
一个解决方案是,使用修改版 slim.service:
 
{{hc|/etc/systemd/system/slim.service|<nowiki>
 
[Unit]
 
Description=SLiM Simple Login Manager
 
After=systemd-user-sessions.service
 
  
[Service]
+
== 相关资源 ==
Type=forking
 
PIDFile=/var/lock/slim.lock
 
ExecStart=/usr/bin/slim -d
 
ExecStop=/bin/kill -9 $MAINPID
 
ExecStopPost=/bin/rm /var/lock/slim.lock
 
  
[Install]
+
*[[Wikipedia:systemd|Wikipedia article]]
WantedBy=graphical.target</nowiki>}}
+
*[https://www.freedesktop.org/wiki/Software/systemd systemd Official web site]
这样关机时 SLiM 就会被 SIGKILL 信号终止。由于 lock 文件也已并移除了,不会导致下次开机出现故障。
+
*[https://www.freedesktop.org/wiki/Software/systemd/Optimizations systemd optimizations]
 
+
*[https://www.freedesktop.org/wiki/Software/systemd/FrequentlyAskedQuestions systemd FAQ]
=== If the CUPS service isn't starting on demand ===
+
*[https://www.freedesktop.org/wiki/Software/systemd/TipsAndTricks systemd Tips and tricks]
I found on my machine, even after running "systemctl enable cups.service", cups would never work until I manually issued "systemctl start cups.service". To remedy this you can manually symlink the cups service so its automatically started at boot: {{bc|<nowiki># sudo ln -s '/usr/lib/systemd/system/cups.service' '/etc/systemd/system/multi-user.target.wants/cups.service'</nowiki>}}
+
*[http://wiki.gentoo.org/wiki/Systemd Gentoo Wiki systemd page]
 
+
*[http://fedoraproject.org/wiki/Systemd Fedora Project - About systemd]
=== Disable warning bell ===
+
*[http://fedoraproject.org/wiki/How_to_debug_Systemd_problems Fedora Project - How to debug systemd problems]
Add command {{ic|xset -b}} to the {{ic|.xinitrc}} file.
+
*[http://fedoraproject.org/wiki/SysVinit_to_Systemd_Cheatsheet Fedora Project - SysVinit to systemd cheatsheet]
Discussion on [https://bbs.archlinux.org/viewtopic.php?pid=1148781 this] forum topic.
+
*[[debian:systemd|Debian Wiki systemd page]]
 
+
*[http://0pointer.de/public/systemd-man/ Manual pages]
== 相关资源 ==
+
*[http://0pointer.de/blog/projects/systemd.html Lennart's blog story], [http://0pointer.de/blog/projects/systemd-update.html update 1], [http://0pointer.de/blog/projects/systemd-update-2.html update 2], [http://0pointer.de/blog/projects/systemd-update-3.html update 3], [http://0pointer.de/blog/projects/why.html summary]
*[http://www.freedesktop.org/wiki/Software/systemd 官方网站]
 
*[http://0pointer.de/public/systemd-man/ 手册页]
 
*[http://freedesktop.org/wiki/Software/systemd/Optimizations systemd 优化]
 
*[http://www.freedesktop.org/wiki/Software/systemd/FrequentlyAskedQuestions 常见问题 FAQ]
 
*[http://www.freedesktop.org/wiki/Software/systemd/TipsAndTricks 小技巧]
 
 
*[http://0pointer.de/public/systemd-ebook-psankar.pdf systemd for Administrators (PDF)]
 
*[http://0pointer.de/public/systemd-ebook-psankar.pdf systemd for Administrators (PDF)]
*[http://en.gentoo-wiki.com/wiki/Systemd Gentoo Wiki 条目]
+
*[https://www.digitalocean.com/community/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-units How To Use Systemctl to Manage Systemd Services and Units ]
*[http://fedoraproject.org/wiki/Systemd Fedora 项目对 systemd 的介绍]
+
*[https://dvdhrm.wordpress.com/2013/08/24/session-management-on-linux/ Session management with systemd-logind]
*[http://fedoraproject.org/wiki/How_to_debug_Systemd_problems 如何调试 systemd 故障]
+
*[[Emacs#Syntax highlighting for systemd Files|Emacs Syntax highlighting for Systemd files]]
*[http://www.h-online.com/open/features/Booting-up-Tools-and-tips-for-systemd-1570630.html Booting up: Tools and tips for systemd, a Linux init tool. In The H]
+
*[http://www.h-online.com/open/features/Control-Centre-The-systemd-Linux-init-system-1565543.html Two] [http://www.h-online.com/open/features/Booting-up-Tools-and-tips-for-systemd-1570630.html part] introductory article in ''The H Open'' magazine.
* [http://0pointer.de/blog/projects/systemd.html 开发者 Lennart 的博文]
 
* [http://0pointer.de/blog/projects/systemd-update.html 一篇更新报告]
 
* [http://0pointer.de/blog/projects/systemd-update-2.html 另一篇更新报告]
 
* [http://0pointer.de/blog/projects/why.html 最新动态]
 
* [http://en.wikipedia.org/wiki/Systemd 维基百科页面]
 
* [http://freedesktop.org/wiki/Software/systemd 项目主页]
 

Latest revision as of 06:18, 29 January 2019

翻译状态: 本文是英文页面 Systemd翻译,最后翻译时间:2019-01-29,点击这里可以查看翻译后英文页面的改动。

摘自项目主页

systemd 是一个 Linux 系统基础组件的集合,提供了一个系统和服务管理器,运行为 PID 1 并负责启动其它程序。功能包括:支持并行化任务;同时采用 socket 式与 D-Bus 总线式激活服务;按需启动守护进程(daemon);利用 Linux 的 cgroups 监视进程;支持快照和系统恢复;维护挂载点和自动挂载点;各服务间基于依赖关系进行精密控制。systemd 支持 SysV 和 LSB 初始脚本,可以替代 sysvinit。除此之外,功能还包括日志进程、控制基础系统配置,维护登陆用户列表以及系统账户、运行时目录和设置,可以运行容器和虚拟机,可以简单的管理网络配置、网络时间同步、日志转发和名称解析等。
注意: Arch Linux 论坛的这篇帖子 详细地解释了 Arch Linux 迁移到 systemd 的原因。

systemd 基本工具

监视和控制systemd的主要命令是systemctl。该命令可用于查看系统状态和管理系统及服务。详见systemctl(1)。、

提示:
  • systemctl 参数中添加 -H <用户名>@<主机名> 可以实现对其他机器的远程控制。该功能使用 SSH 连接。
  • Plasma 用户可以安装 systemctl 图形前端 systemd-kcmAUR。安装后可以在 System administration 下找到。

分析系统状态

显示 系统状态

$ systemctl status

输出激活的单元:

$ systemctl

以下命令等效:

$ systemctl list-units

输出运行失败的单元:

$ systemctl --failed

所有可用的单元文件存放在 /usr/lib/systemd/system//etc/systemd/system/ 目录(后者优先级更高)。查看所有已安装服务:

$ systemctl list-unit-files

显示 cgroup slice, 内存和父 PID:

$ systemctl status pid

使用单元

一个单元配置文件可以描述如下内容之一:系统服务(.service)、挂载点(.mount)、sockets(.sockets) 、系统设备(.device)、交换分区(.swap)、文件路径(.path)、启动目标(.target)、由 systemd 管理的计时器(.timer)。详情参阅 systemd.unit(5)

使用 systemctl 控制单元时,通常需要使用单元文件的全名,包括扩展名(例如 sshd.service )。但是有些单元可以在 systemctl 中使用简写方式。

  • 如果无扩展名,systemctl 默认把扩展名当作 .service 。例如 netcfgnetcfg.service 是等价的。
  • 挂载点会自动转化为相应的 .mount 单元。例如 /home 等价于 home.mount
  • 设备会自动转化为相应的 .device 单元,所以 /dev/sda2 等价于 dev-sda2.device
注意: 有一些单元的名称包含一个 @ 标记(例如: name@string.service ),这意味着它是模板单元 name@.service 的一个 实例string 被称作实例标识符,在 systemctl 调用模板单元时,会将其当作一个参数传给模板单元,模板单元会使用这个传入的参数代替模板中的 %I 指示符。

在实例化之前,systemd 会先检查 name@string.suffix 文件是否存在(如果存在,就直接使用这个文件,而不是模板实例化)。大多数情况下,包含 @ 标记都意味着这个文件是模板。如果一个模板单元没有实例化就调用,该调用会返回失败,因为模板单元中的 %I 指示符没有被替换。

提示:
  • 下面的大部分命令都可以跟多个单元名, 详细信息参见 systemctl(1)
  • systemctl命令在enabledisablemask子命令中增加了--now选项,可以实现激活的同时启动服务,取消激活的同时停止服务。
  • 一个软件包可能会提供多个不同的单元。如果你已经安装了软件包,可以通过pacman -Qql package | grep systemd命令检查这个软件包提供了哪些单元。

立即激活单元:

# systemctl start <单元>

立即停止单元:

# systemctl stop <单元>

重启单元:

# systemctl restart <单元>

重新加载配置:

# systemctl reload <单元>

输出单元运行状态:

$ systemctl status <单元>

检查单元是否配置为自动启动:

$ systemctl is-enabled <单元>

开机自动激活单元:

# systemctl enable <单元>

设置单元为自动启动并立即启动这个单元:

# systemctl enable --now unit

取消开机自动激活单元:

# systemctl disable <单元>

禁用一个单元(禁用后,间接启动也是不可能的):

# systemctl mask <单元>

取消禁用一个单元:

# systemctl unmask <单元>

显示单元的手册页(必须由单元文件提供):

# systemctl help <单元>

重新载入 systemd 系统配置,扫描单元文件的变动。注意这里不会重新加载变更的单元文件。参考上面的 reload 示例。

# systemctl daemon-reload

电源管理

安装 polkit 后才能以普通用户身份使用电源管理。

如果你正登录在一个本地的 systemd-logind 用户会话,且当前没有其它活动的会话,那么以下命令无需 root 权限即可执行。否则(例如,当前有另一个用户登录在某个 tty ), systemd 将会自动请求输入root密码。

重启:

$ systemctl reboot

退出系统并关闭电源:

$ systemctl poweroff

待机:

$ systemctl suspend

休眠:

$ systemctl hibernate

混合休眠模式(同时休眠到硬盘并待机):

$ systemctl hybrid-sleep

编写单元文件

systemd 单元文件的语法来源于 XDG 桌面项配置文件.desktop文件,最初的源头则是Microsoft Windows的.ini文件。单元文件可以从多个地方加载,systemctl show --property=UnitPath 可以按优先级从低到高显示加载目录:

  • /usr/lib/systemd/system/ :软件包安装的单元
  • /etc/systemd/system/ :系统管理员安装的单元
注意:
  • systemd 运行在用户模式下时,使用的加载路径是完全不同的。
  • systemd 单元名仅能包含 ASCII 字符,下划线和点号和有特殊意义的字符('@', '-')。其它字符需要用 C-style "\x2d" 替换。参阅 systemd.unit(5)systemd-escape(1)

单元文件的语法,可以参考系统已经安装的单元,也可以参考 systemd.service(5) 中的EXAMPLES章节

提示: # 开头的注释可能也能用在 unit-files 中,但是只能在新行中使用。不要在 systemd 的参数后面使用行末注释, 否则 unit 将会启动失败。

处理依赖关系

使用 systemd 时,可通过正确编写单元配置文件来解决其依赖关系。典型的情况是,单元 A 要求单元 BA 启动之前运行。在此情况下,向单元 A 配置文件中的 [Unit] 段添加 Requires=BAfter=B 即可。若此依赖关系是可选的,可添加 Wants=BAfter=B 。请注意 Wants=Requires= 并不意味着 After= ,即如果 After= 选项没有制定,这两个单元将被并行启动。

依赖关系通常被用在服务(service)而不是目标(target)上。例如, network.target 一般会被某个配置网络接口的服务引入,所以,将自定义的单元排在该服务之后即可,因为 network.target 已经启动。

服务类型

编写自定义的 service 文件时,可以选择几种不同的服务启动方式。启动方式可通过配置文件 [Service] 段中的 Type= 参数进行设置。

  • Type=simple :(默认值) systemd认为该服务将立即启动。服务进程不会 fork 。如果该服务要启动其他服务,不要使用此类型启动,除非该服务是socket 激活型。
  • Type=forking :systemd认为当该服务进程fork,且父进程退出后服务启动成功。对于常规的守护进程(daemon),除非你确定此启动方式无法满足需求,使用此类型启动即可。使用此启动类型应同时指定 PIDFile=,以便 systemd 能够跟踪服务的主进程。
  • Type=oneshot :这一选项适用于只执行一项任务、随后立即退出的服务。可能需要同时设置 RemainAfterExit=yes 使得 systemd 在服务进程退出之后仍然认为服务处于激活状态。
  • Type=notify :与 Type=simple 相同,但约定服务会在就绪后向 systemd 发送一个信号。这一通知的实现由 libsystemd-daemon.so 提供。
  • Type=dbus :若以此方式启动,当指定的 BusName 出现在DBus系统总线上时,systemd认为服务就绪。
  • Type=idlesystemd会等待所有任务处理完成后,才开始执行 idle 类型的单元。其他行为与 Type=simple 类似。

type 的更多解释可以参考 systemd.service(5)

修改现存单元文件

为了避免和 pacman 冲突,不应该直接编辑软件包提供的文件。有两种方法可以不改动原始文件就做到修改单元文件:创建一个优先级更高的本地单元文件或创建一个片段,应用到原始单元文件之上。两种方法都需要在修改后重新加载单元,用 systemctl edit 编辑单元(会自动重载单元)或通过下面命令重新加载单元:

# systemctl daemon-reload
提示:
  • systemd-delta 命令用来查看哪些单元文件被覆盖、哪些被修改。系统维护的时候需要及时了解哪些单元已经有了更新。
  • 使用 systemctl cat unit 可以查看单元的内容和所有相关的片段.

替换单元文件

要替换 /usr/lib/systemd/system/unit, 创建文件 /etc/systemd/system/unit 并重新启用单元以更新链接:

# systemctl reenable unit

或者运行:

# systemctl edit --full unit

这将会在记事本中打开 /etc/systemd/system/unit,如果文件不存在,可以将安装的版本复制到这里,在编辑完成之后,会自动加载新版本。

注意: 即使 Pacman 更新了新的单元文件,软件包中的版本也不会被使用,所以这个方式会增加系统维护的难度,推荐使用下面一种方法。

附加配置片段

要附加配置片段,先创建名为 /etc/systemd/system/<单元名>.d/ 的目录,然后放入 *.conf 文件,其中可以添加或重置参数。这里设置的参数优先级高于原来的单元文件。下面的更新方式比较简单:

# systemctl edit unit

这将会在编辑器中打开文件 /etc/systemd/system/unit.d/override.conf,编辑完成之后自动加载。

Note: 并不是所有参数都会被子配置文件覆盖。例如要修改 Conflicts= 就必须 替换原始文件

重置到软件包版本

要回退单元的变更,使用 systemctl edit 并执行:

# systemctl revert unit

示例

例如,如果想添加一个额外的依赖,创建如下文件即可:

/etc/systemd/system/<unit>.d/customdependency.conf
[Unit]
Requires=<新依赖>
After=<新依赖>

要修改一个非 oneshot 单元的 ExecStart 命令,创建下面文件:

/etc/systemd/system/unit.d/customexec.conf
[Service]
ExecStart=
ExecStart=new command

修改 ExecStart 前必须将其置空,参见 ([1] 。所有可能多次赋值的变量都需要这个操作,例如定时器的 OnCalendar

下面是自动重启服务的一个例子:

/etc/systemd/system/unit.d/restart.conf
[Service]
Restart=always
RestartSec=30

目标(target)

运行级别(runlevel)是一个旧的概念。现在,systemd 引入了一个和运行级别功能相似又不同的概念——目标(target)。不像数字表示的启动级别,每个目标都有名字和独特的功能,并且能同时启用多个。一些目标继承其他目标的服务,并启动新服务。systemd 提供了一些模仿 sysvinit 运行级别的目标,仍可以使用旧的 telinit 运行级别 命令切换。

获取当前目标

不要使用 runlevel 命令了:

$ systemctl list-units --type=target

创建自定义目标

sysvinit 中有明确定义的运行级别(如:0、1、3、5、6)与 systemd 中特定的 目标 存在一一对应的关系。然而,对于用户自定义运行级别(2、4)却没有。如需要同样功能,建议你以原有运行级别所对应的 systemd 目标为基础,新建一个/etc/systemd/system/<目标名>.target(可参考/usr/lib/systemd/system/graphical.target), 然后创建目录/etc/systemd/system/<目标名>.wants,并向其中加入需启用的服务链接(指向/ur/lib/systemd/system/)。

"SysV 运行级别" 与 "systemd 目标" 对照表

SysV 运行级别 Systemd 目标 注释
0 runlevel0.target, poweroff.target 中断系统(halt)
1, s, single runlevel1.target, rescue.target 单用户模式
2, 4 runlevel2.target, runlevel4.target, multi-user.target 用户自定义运行级别,通常识别为级别3。
3 runlevel3.target, multi-user.target 多用户,无图形界面。用户可以通过终端或网络登录。
5 runlevel5.target, graphical.target 多用户,图形界面。继承级别3的服务,并启动图形界面服务。
6 runlevel6.target, reboot.target 重启
emergency emergency.target 急救模式(Emergency shell)

切换当前运行目标

systemd中,运行目标通过“目标单元”访问。通过如下命令切换:

# systemctl isolate graphical.target

该命令仅更改当前运行目标,对下次启动无影响。这等价于sysvinit中的 telinit 3telinit 5 命令。

更改开机默认启动目标

开机启动的目标是 default.target,默认链接到 graphical.target (大致相当于原来的运行级别5)。

systemctl 检查当前的默认启动目标:

# systemctl get-default

systemctl 修改default.target以变更开机默认启动目标:

$ systemctl set-default multi-user.target
Removed /etc/systemd/system/default.target.
Created symlink /etc/systemd/system/default.target -> /usr/lib/systemd/system/graphical.target.

另一方法是向bootloader添加内核参数

  • systemd.unit=multi-user.target (大致相当于运行级别3)
  • systemd.unit=rescue.target (大致相当于运行级别1)

默认目标顺序

Systemd 根据下面顺序选择 default.target

  1. 上面的内核参数
  2. /etc/systemd/system/default.target 软链接
  3. /usr/lib/systemd/system/default.target 软链接

临时文件

/usr/lib/tmpfiles.d//etc/tmpfiles.d/ 中的文件描述了 systemd-tmpfiles 如何创建、清理、删除临时文件和目录,这些文件和目录通常存放在 /run/tmp 中。配置文件名称为 /etc/tmpfiles.d/<program>.conf。此处的配置能覆盖 /usr/lib/tmpfiles.d/ 目录中的同名配置。

临时文件通常和服务文件同时提供,以生成守护进程需要的文件和目录。例如 Samba 服务需要目录 /run/samba 存在并设置正确的权限位,就象这样:

/usr/lib/tmpfiles.d/samba.conf
D /run/samba 0755 root root

此外,临时文件还可以用来在开机时向特定文件写入某些内容。比如,要禁止系统从USB设备唤醒,利用旧的 /etc/rc.local 可以用 echo USBE > /proc/acpi/wakeup,而现在可以这么做:

/etc/tmpfiles.d/disable-usb-wake.conf
w /proc/acpi/wakeup - - - - USBE

详情参见systemd-tmpfiles(8)tmpfiles.d(5)

注意: 该方法不能向 /sys 中的配置文件添加参数,因为 systemd-tmpfiles-setup 有可能在相关模块加载前运行。这种情况下,需要首先通过 modinfo <模块名> 确认需要的参数,然后在 /etc/modprobe.d 目录下的配置文件中修改配置参数。另外,还可以使用 udev 规则,在设备就绪时设置相应属性。

定时器

一个定时器是一个以 .timer 为结尾的单元配置文件并包含由 systemd 控制和监督的信息。systemd/Timers (简体中文)

注意: 定时器很大程度上可取代 cronsystemd/Timers (简体中文)#替代 cron

挂载

因为 systemd 也负责按 /etc/fstab 挂载目录。在系统启动和重新加载系统管理器时,systemd-fstab-generator(8) 会将 /etc/fstab 中的配置转化为 systemd 单元。

systemd 扩展了 fstab 的传统功能,提供了额外的挂载选项。例如可以确保一个挂载仅在网络已经连接时进行,或者仅当另外一个分区已挂载时再挂载。这些选项通常以 x-systemd. 开头,systemd.mount(5) 中包含了完整说明。

automounting 也是一个例子,可以在使用时,而不是启动时挂载分区,详情请参考 fstab#Automount with systemd

GPT 分区自动挂载

GPT 分区磁盘系统上,systemd-gpt-auto-generator(8) 会按照 可探测分区规范 进行挂载。可以在 fstab 中忽略。

要禁用自动挂载,请修改分区的 类型 GUID 或设置分区属性 63 位 "不自动挂载",详情参考 gdisk#Prevent GPT partition automounting

Tips and tricks

Running services after the network is up

To delay a service after the network is up, include the following dependencies in the .service file:

/etc/systemd/system/foo.service
[Unit]	
...
Wants=network-online.target
After=network-online.target	
...

The network wait service of the particular application that manages the network, must also be enabled so that network-online.target properly reflects the network status.

  • For the ones using NetworkManager, enable NetworkManager-wait-online.service.
  • If using systemd-networkd, systemd-networkd-wait-online.service is by default enabled automatically whenever systemd-networkd.service has been enabled; check this is the case with systemctl is-enabled systemd-networkd-wait-online.service, there is no other action needed.

For more detailed explanations see Running services after the network is up in the systemd wiki.

Enable installed units by default

Tango-view-fullscreen.pngThis article or section needs expansion.Tango-view-fullscreen.png

Reason: How does it work with instantiated units? (Discuss in Talk:Systemd (简体中文)#)

Arch Linux ships with /usr/lib/systemd/system-preset/99-default.preset containing disable *. This causes systemctl preset to disable all units by default, such that when a new package is installed, the user must manually enable the unit.

If this behavior is not desired, simply create a symlink from /etc/systemd/system-preset/99-default.preset to /dev/null in order to override the configuration file. This will cause systemctl preset to enable all units that get installed—regardless of unit type—unless specified in another file in one systemctl preset's configuration directories. User units are not affected. See the manpage for systemd.preset for more information.

Note: Enabling all units by default may cause problems with packages that contain two or more mutually exclusive units. systemctl preset is designed to be used by distributions and spins or system administrators. In the case where two conflicting units would be enabled, you should explicitly specify which one is to be disabled in a preset configuration file as specified in the manpage for systemd.preset.

Sandboxing application environments

A unit file can be created as a sandbox to isolate applications and their processes within a hardened virtual environment. systemd leverages namespaces, white-/blacklisting of Capabilities, and control groups to container processes through an extensive execution environment configuration.

The enhancement of an existing systemd unit file with application sandboxing typically requires trial-and-error tests accompanied by the generous use of strace, stderr and journalctl error logging and output facilities. You may want to first search upstream documentation for already done tests to base trials on.

Some examples on how sandboxing with systemd can be deployed:

  • CapabilityBoundingSet defines a whitelisted set of allowed capabilities, but may also be used to blacklist a specific capability for a unit.
    • The CAP_SYS_ADM capability, for example, which should be one of the goals of a secure sandbox: CapabilityBoundingSet=~ CAP_SYS_ADM

疑难解答

寻找错误

这个例子中的失败的服务是 systemd-modules-load :

1. 通过 systemd 寻找启动失败的服务:

$ systemctl --state=failed
systemd-modules-load.service   loaded failed failed  Load Kernel Modules

或者使用 systemd 消息:

$ journalctl -fp err

2. 我们发现了启动失败的 systemd-modules-load 服务. 我们想知道更多信息:

$ systemctl status systemd-modules-load
systemd-modules-load.service - Load Kernel Modules
   Loaded: loaded (/usr/lib/systemd/system/systemd-modules-load.service; static)
   Active: failed (Result: exit-code) since So 2013-08-25 11:48:13 CEST; 32s ago
     Docs: man:systemd-modules-load.service(8).
           man:modules-load.d(5)
  Process: 15630 ExecStart=/usr/lib/systemd/systemd-modules-load (code=exited, status=1/FAILURE)

如果没列出 Process ID, 通过 systemctl 重新启动失败的服务 ( 例如 systemctl restart systemd-modules-load )

3. 现在得到了 PID ,你就可以进一步探查错误的详细信息了.通过下列的命令收集日志,PID 参数是你刚刚得到的 Process ID (例如 15630):

$ journalctl -b _PID=15630
-- Logs begin at Sa 2013-05-25 10:31:12 CEST, end at So 2013-08-25 11:51:17 CEST. --
Aug 25 11:48:13 mypc systemd-modules-load[15630]: Failed to find module 'blacklist usblp'
Aug 25 11:48:13 mypc systemd-modules-load[15630]: Failed to find module 'install usblp /bin/false'

4. 我们发现有些内核模块的配置文件不正确,因此在 /etc/modules-load.d/ 中检查一下:

$ ls -Al /etc/modules-load.d/
...
-rw-r--r--   1 root root    79  1. Dez 2012  blacklist.conf
-rw-r--r--   1 root root     1  2. Mär 14:30 encrypt.conf
-rw-r--r--   1 root root     3  5. Dez 2012  printing.conf
-rw-r--r--   1 root root     6 14. Jul 11:01 realtek.conf
-rw-r--r--   1 root root    65  2. Jun 23:01 virtualbox.conf
...

5. 错误消息 Failed to find module 'blacklist usblp' 也许和 blacklist.conf 相关. 让我们注释掉第三步发现的错误的选项:

/etc/modules-load.d/blacklist.conf
# blacklist usblp
# install usblp /bin/false

6. 最后重新启动 systemd-modules-load 服务:

# systemctl start systemd-modules-load

如果服务成功启动,不会有任何输出.如果你还是遇到了错误,回到步骤三,获得新的 PID 来跟踪日志并解决错误.

可以像这样确认服务成功启动:

$ systemctl status systemd-modules-load
systemd-modules-load.service - Load Kernel Modules
   Loaded: loaded (/usr/lib/systemd/system/systemd-modules-load.service; static)
   Active: active (exited) since So 2013-08-25 12:22:31 CEST; 34s ago
     Docs: man:systemd-modules-load.service(8)
           man:modules-load.d(5)
 Process: 19005 ExecStart=/usr/lib/systemd/systemd-modules-load (code=exited, status=0/SUCCESS)
Aug 25 12:22:31 mypc systemd[1]: Started Load Kernel Modules.

诊断启动问题

使用如下内核参数引导: systemd.log_level=debug systemd.log_target=kmsg log_buf_len=1M

更多有关调试的信息,参见该文

诊断一个服务

如果某个 systemd 服务的工作状况不合预期,希望调试的话,设置 SYSTEMD_LOG_LEVEL 环境变量debug . 例如以调试模式运行 systemd-networkd 服务:

在此服务的配置文件片段中加入:

[Service]
Environment=SYSTEMD_LOG_LEVEL=debug

或者等价的,临时编辑系统单元文件,例如:

  1. SYSTEMD_LOG_LEVEL=debug /lib/systemd/systemd-networkd

重启 systemd-networkd 服务,用 --follow 选项检查日志。

关机/重启十分缓慢

如果关机特别慢(甚至跟死机了一样),很可能是某个拒不退出的服务在作怪。systemd 会等待一段时间,然后再尝试杀死它。请阅读这篇文章,确认你是否是该问题受害者。

短时进程无日志记录

journalctl -u foounit.service 没有显示某个短时进程的任何输出,那么改用 PID 试试。例如,若 systemd-modules-load.service 执行失败,那么先用 systemctl status systemd-modules-load 查询其 PID(比如是123),然后检索该 PID 相关的日志 journalctl -b _PID=123。运行时进程的日志元数据(诸如 _SYSTEMD_UNIT 和 _COMM)被乱序收集在 /proc 目录。要修复该问题,必须修改内核,使其通过套接字连接来提供上述数据,该过程类似于 SCM_CREDENTIALS。

禁止在程序崩溃时转储内存

要使用老的内核转储,创建下面文件:

/etc/sysctl.d/49-coredump.conf
kernel.core_pattern = core
kernel.core_uses_pid = 0

然后运行:

# /usr/lib/systemd/systemd-sysctl

同样可能需要执行“unlimit”设置文件大小:

$ ulimit -c unlimited

更多信息请参阅 sysctl.d/proc/sys/kernel 文档

启动的时间太长

不少用户用了 systemd-analyze 命令以后报告启动的时间比预计的要长,通常会说 systemd-analyze 分析结果表示 NetworkManager 占据了太多的启动的时间.

有些用户的问题是 /var/log/journal 文件夹似乎过大.这也许也会对像systemctl statusjournalctl 的命令有影响.一种解决方案是删除其中的文件 (但最好将它们备份到某处) 然后限制日志文件的大小.

systemd-tmpfiles-setup.service 在启动时启动失败

从 systemd 219 开始, /usr/lib/tmpfiles.d/systemd.conf 指定 /var/log/journal 的 ACL 属性和目录, 因此日志所在的文件系统上要启用ACL.

参阅 Access Control Lists#Enabling ACL 获得如何包含 /var/log/journal 启动 ACL 的详细信息.

启动时显示的 systemd 版本和安装版本不一致

需要 重新生成 initramfs

提示: 可以使用 pacman 钩子在更新 systemd时重新生成 initramfs。参考 这个帖子Pacman#Hooks.

禁用远程机器的 emergency 模式

如果远程机器位于云主机,emergency 模式会导致系统无法远程连接,可以通过下面方式禁用紧急模式:

# systemctl mask emergency.service
# systemctl mask emergency.target

相关资源