systemd (简体中文)

From ArchWiki
Revision as of 04:28, 15 July 2012 by Cuihao (Talk | contribs)

Jump to: navigation, search

Summary help replacing me
systemd 是 Linux 下的一款系统和服务管理器,兼容 SysV 和 LSB 的启动脚本(init scripts)。systemd的特性有:支持积极并行化任务;同时采用socket式与D-Bus总线式激活服务;按需启动守护进程(daemon);利用 Linux 的cgroups监视进程;支持快照和系统恢复;维护挂载点;各服务间基于依赖关系进行精密控制。systemd 完全可以替代 Arch 默认的 sysvinit 启动系统。
相关页面
Systemd/Services
相关链接
开发者 Lennart 的博文
一篇更新报告
另一篇更新报告
最新动态
维基百科页面
项目主页

安装

systemd 可以和 Arch 默认的启动系统(initscripts)共存,通过添加/删除内核参数 init=/bin/systemd 切换。马上开始试用 systemd:

  1. 从[core]仓库安装 systemd
  2. 在启动引导器添加内核参数 init=/bin/systemd
  3. (可选)如果希望完全使用 systemd,可以移除 initscripts 并安装 systemd-sysvcompat。删除 sysvinit 后,由该包提供一些基本命令(initreboot 等)的链接。之后,可以删除上一步添加的内核参数。
  4. 建议安装 systemd-arch-units,该包提供了常用系统服务的 systemd 原生服务文件。
  5. 启用原来 rc.conf 中配置的自启动服务,systemd 无法完全兼容该文件。
警告: udev 和很多其他系统软件要求 /usr 在启动早期就挂载。如果 /usr 和根目录不在同一分区,那么必须做一些额外设置。参见 mkinitcpio相关页面 以及 freedesktop.org的相关页面

原生 systemd 配置文件

如果下列文件不存在,systemd 会从 /etc/rc.conf 读取相关配置。

小贴士: 某些文件可能需要手动创建。

主机名

设置主机名为“myhostname”:

/etc/hostname
myhostname

控制台和键盘布局

/etc/vconsole.conf 文件用来配置虚拟控制台,包括键盘映射和控制台字体:

/etc/vconsole.conf
KEYMAP=us
FONT=lat9w-16
FONT_MAP=8859-1_to_uni

Locale

更多内容参阅 man locale.conf

/etc/locale.conf
LANG=en_US.UTF-8
LC_COLLATE=C

时区

更多内容参阅 man 5 timezone

/etc/timezone
Asia/Shanghai
注意: 设置该文件后仍需配置 /etc/localtime

硬件时钟

systemd 默认识别硬件时钟为协调世界时(UTC),也推荐这样设置。处理夏令时有些麻烦,如果夏令时调整发生在关机时,下次启动时时间会出现问题(更多信息)。最新的内核直接从实时时钟芯片(RTC)读取时间,不使用 hwclock,内核把从 RTC 读取的时间当作 UTC 处理。所以如果硬件时间是地方时,系统启动一开始识别的时间是错误的,之后很快会进行矫正。这可能导致一些问题(尤其是时间倒退时)。

如果同时安装了 Windows 操作系统(默认使用地方时),那么一般 RTC 会被设置为地方时。Windows 其实也能处理 UTC,在注册表中设置下列DWORD键值为1即可:

HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\RealTimeIsUniversal
警告: 在最新的 Windows 7、 Vista SP2 上,此设置会导致网络时间同步无法使用。而早期的版本中,此设置会导致系统从睡眠、待机唤醒后出现故障。此外,Windows 还可能因此无法处理夏令时调整

如果不想因此弄乱 Windows,systemd 也可以接受本地时:

/etc/adjtime
 
0.0 0.0 0.0
0
LOCAL
注意: The other parameters are still needed but are ignored by systemd. (译者不理解……)
注意: 推荐使用NTP服务来确保硬件时钟同步。

开机加载内核模块

systemd 读取 /etc/modules-load.d/ 中的配置,加载内核模块。配置文件名称通常为 /etc/modules-load.d/<program>.conf。格式很简单,一行一个要读取的模块名,而空行以及第一个非空格字符为#;的行会被忽略,如:

/etc/modules-load.d/virtio-net.conf
# Load virtio-net.ko at boot
virtio-net

另见:Kernel modules (简体中文)#选项

禁用内核模块

禁用内核模块的方法和 Arch 默认的 initscripts 相同,因为该过程实际由 kmod 处理。参见:Kernel modules (简体中文)#黑名单

临时文件

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

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

/usr/lib/tmpfiles.d/samba.conf
D /var/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 并不原生支持 /etc/rc.local

详情参见 man tmpfiles.d

挂载网络文件系统

/etc/fstab 中设定的网络文件系统(如 NFSSamba)无需配置即可正常工作,systemd 将确保网络文件系统在网络链接就绪后挂载。

也可以使用自动挂载功能,使得网络文件系统仅在访问时挂载。添加 x-systemd.device-timeout=超时时间/etc/fstab 的 <options> 部分即可。

详情参见 man systemd.mount

用 systemd 替代 acpid

systemd 能够处理某些电源相关的 ACPI 事件,通过 /etc/systemd/logind.conf 的下列选项配置:

  • HandlePowerKey:按下电源键后关机
  • HandleSleepKey:按下键盘Sleep键后待机
  • HandleLidSwitch:合上笔记本盖后待机

当选项设置为 no-session 时,事件仅在无用户登录时才会触发。设置为 any-session 时,仅在单用户会话时触发。详情参见 man logind.conf

不应在 GNOMEXfce 这类能处理 ACPI 事件的桌面环境中使用上述选项。但如果不用图形界面,或者使用 i3awesome 这样简单的桌面环境时,该功能可以替代 acpid 处理 ACPI 事件。

单元(unit)

一个单元配置文件可以描述如下内容之一:系统服务、socket、系统设备、挂载点、交换分区/文件、启动目标(target)、文件系统路径、由 systemd 管理的计时器。文件格式受 .desktop 文件启发,而最初起源是 Windows 下的 .ini 文件。详情参见 man systemd.unit

systemd 命令

  • systemctl:控制 systemd 状态,包括服务的启动和停止。
  • systemd-cgls:以树形递归显示指定 Linux 控制组(cgroup)的内容
  • systemadm:控制 systemd 状态的图形前端(由 AUR 软件包 systemd-ui-gitAUR 提供)。

详情参见上述工具的 man 手册页。

小贴士: systemctl 参数中添加 -H <用户名>@<主机名> 可以实现对其他机器的远程控制。该过程使用 SSH 链接。

分析系统状态

输出激活的单元:

$ systemctl

以下命令等效:

$ systemctl list-units

输出运行失败的单元:

$ systemctl --failed

所有可用的单元文件存放在 /usr/lib/systemd/system//etc/systemd/system/ 目录(后者优先级更高)。

使用单元

一个单元可以是系统服务(.service)、挂载点(.mount)、sockets(.sockets)。使用 systemctl 控制单元时,必须使用单元文件的全名,包括扩展名(例如 netcfg.service)。详情参见 man systemd.unit

立即激活单元:

# systemctl start <unit>

立即停止单元:

# systemctl stop <unit>

重启单元:

# systemctl restart <unit>

命令单元重新读取配置:

# systemctl reload <unit>

输出单元运行状态:

$ systemctl status <unit>

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

$ systemctl is-enabled <unit>

开机自动激活单元:

# systemctl enable <unit>

取消开机自动激活单元:

# systemctl disable <unit>

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

$ systemctl help <unit>

电源管理

当系统中仅有一个本地用户会话时,执行下列命令无需 root 权限。否则,systemd 会要求输入 root 密码。

重启:

$ systemctl reboot

退出系统并停止电源(shut down and power-off):

$ systemctl poweroff

退出系统并中断(shut down and halt):

$ systemctl halt

待机:

$ systemctl suspend

休眠:

$ systemctl hibernate

启动级别(runlevel)/目标(target)

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

获取当前启动级别/目标

不要使用 runlevel 命令了:

# systemctl list-units --type=target

创建新目标

在 Fedora 中,启动级别 0、1、3、5、6 都被赋予特定用途,并且都对应一个 systemd 的目标。然而,没有什么很好的移植用户定义的启动级别(2、4)的方法。要实现类似功能,可以以原有的启动级别为基础,创建一个新的目标 /etc/systemd/system/<新目标>(可以参考 /usr/lib/systemd/system/graphical.target),创建 /etc/systemd/system/<新目标>.wants 目录,向其中加入额外服务的链接(指向 /usr/lib/systemd/system/ 中的单元文件)。

目标表

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

该命令对下次启动无影响。

修改默认启动级别/目标

开机启动进的目标是 default.target,默认链接到 graphical.target (大致相当于原来的启动级别5)。可以通过内核参数更改默认启动级别:

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

另一个方法是修改 default.target。可以通过 systemctl 修改它:

# systemctl enable multi-user.target

命令执行情况由 systemctl 显示:链接 /etc/systemd/system/default.target 被创建,指向新的默认启动级别。 该方法当且仅当目标配置文件中有以下内容时有效:

[Install]
Alias=default.target

目前,multi-user.targetgraphical.target 都包含这段内容。

启动桌面环境

使用登录管理器

通过启动登录管理器(或称显示管理器),即可进行图形界面登录。目前,Arch 提供了 GDMKDMSLiMXDMLXDM 的 systemd 服务文件。以 KDM 为例,配置开机启动:

# systemctl enable kdm.service

执行上述命令后,登录管理器应当能正常工作了。如果不是的话,很可能是因为你修改了default.target。默认情况应当如下:

# ls -l /etc/systemd/system/default.target
/etc/systemd/system/default.target -> /usr/lib/systemd/system/graphical.target

删除被修改的 default.target,systemd 会自动使用默认配置(即 graphical.target):

# rm /etc/systemd/system/default.target

如果使用 /etc/locale.conf 配置了 locale,那么还需要添加以下项到 /etc/environment

/etc/environment
LANG=en_US.utf8

使用服务文件

注意: 使用此方法的话,用户无法创建 PAM 会话。因此,ConsoleKit(赋予用户关机、操作声音设备等权限的程序)无法正常工作。更好的方案,参见:Automatic_login_to_virtual_console#With_systemd

这个方法不需要登录管理器,直接启动了X。方法是创建一个新的服务文件:

/etc/systemd/system/graphical.target.wants/xinit.service
[Unit]
Description=Direct login to X
After=systemd-user-sessions.service

[Service]
ExecStart=/bin/su <username> -l -c "/bin/bash --login -c xinit"

[Install]
WantedBy=graphical.target

systemd 日志

自版本 38 起,systemd 提供了自己日志系统(logging system),称为 journal(还是日志的意思)。

使用 systemd 日志,无需额外安装日志服务(syslog)。读取日志的命令:

# journalctl

日志记录在虚拟文件系统内(/run/systemd/journal),所以重启后就会消失。要保留的话,需手动创建目录 /var/log/journal/

# mkdir /var/log/journal/

日志大小限制

如果按上面的操作保留日志的话,默认日志最大限制为所在文件系统容量的 10%,即:如果 /var/log/journal 储存在 50GiB 的根分区中,那么日志最多存储 5GiB 数据。可以修改 /etc/systemd/journald.conf 中的 SystemMaxUse 来指定该最大限制。如限制日志最大 50MiB:

SystemMaxUse=50M

详情参见 man journald.conf.

配合传统日志服务(syslog)

systemd 提供了 socket /run/systemd/journal/syslog,以兼容传统日志服务。所有系统信息都会被传入。要使传统日志服务工作,需要让服务链接该 socket,而非 /dev/loghttp://lwn.net/Articles/474968/ 官方说明)。以 Arch 原先默认的 syslog-ng 服务为例,修改 /etc/syslog-ng/syslog-ng.conf 的 source 部分:

source src {
    unix-dgram("/run/systemd/journal/syslog");
    internal();
    file("/proc/kmsg");
};

设置开机启动 syslog-ng:

# systemctl enable syslog-ng.service

systemd 的日志服务默认也会从 /proc/kmsg 读取内核信息,这就做了和传统日志服务相同的事(systemd-devel 相关帖子)。可以修改 /etc/systemd/journald.conf 来关闭 systemd 日志的这一功能:

ImportKernel=no

网络

DHCP 动态获取 IP

如果使用 DHCP 动态获取 IP,可以使用 systemd-arch-units 软件包提供的 dhcpcd@.service。例如,为 eth0 启用 DHCP:

# systemctl start dhcpcd@eth0.service

设置开机自动配置:

# systemctl enable dhcpcd@.service

注意,这样只会启用 eth0 的自动配置。如果还要配置其他链接,需要手动创建软连接:

# ln -s '/usr/lib/systemd/system/dhcpcd@.service' '/etc/systemd/system/multi-user.target.wants/dhcpcd@eth1.service'

其他配置方式

对于静态IP、无线网络或其他上网方式,建议使用 netcfgNetworkManager,两者都提供了 systemd 服务文件。

如果使用静态IP,又不想用额外的工具,可以手动创建一个服务

Arch 整合

Integration with Arch's classic configuration is accomplished via the initscripts-systemd package. This is an optional package containing unit files and scripts needed to emulate Arch's initscripts, which can be used to ease the transition from sysVinit to systemd.

/etc/inittab is not used at all.

/etc/rc.local and /etc/rc.local.shutdown can be run at startup and shutdown by enabling rc-local.service and rc-local-shutdown.service.

Warning: Usage of this package is not recommended. In particular, arch-load-modules.service and arch-daemons.target are unsupported as a long-term solution and will be removed in the future. When ever possible, use native systemd configuration files instead.

Most people will not need all (if any) of these units, and they can be easily disabled with:

# systemctl disable <unitfile>

The plan is to remove most of the functionality from this package as soon as it is handled elsewhere (mostly in udev/systemd/kernel).

rc.conf

Some variables in /etc/rc.conf are respected by this glue work. For a pure systemd setup it is recommended to use the native systemd configuration files which will take precedence over /etc/rc.conf.

Supported variables:

  • LOCALE
  • KEYMAP
  • CONSOLEFONT
  • CONSOLEMAP
  • HOSTNAME
  • MODULES
  • DAEMONS: Ordering and blacklisting is respected, if a native systemd service file by the same name as a daemon exists, it will take precedence, this logic can be disabled by systemctl disable arch-daemons.target

Not supported variables and systemd configuration:

  • TIMEZONE: Please symlink /etc/localtime to your zoneinfo file manually.
  • HARDWARECLOCK: See Hardware clock time.
  • USELVM: use lvm.service provided by systemd-arch-units instead.
  • USECOLOR

The following is a brief description of the functionality of each of them. Alternative solutions are provided as a migration plan away from the functionality provided by this package.

rc-local.service / rc-local-shutdown.service

Runs /etc/rc.local (resp., /etc/rc.local.shutdown) on boot (resp., shutdown).

arch-daemons.target

Parses the DAEMONS array in /etc/rc.conf and starts the services. If a native systemd unit exists (by the same name) for a given daemon, this is used; otherwise, the script in /etc/rc.d/ is used to control the unit.

Alternative: use native unit files from the systemd-arch-units package.

arch-modules-load.service

Creates a list of modules to be loaded based on /etc/rc.conf (see /etc/modules-load.d/rc.conf).

Alternative: create a *.conf for your modules in /etc/modules-load.d/.

FAQ

For an up-to-date list of known issues, look at the upstream TODO.

Template:FAQ

Template:FAQ

Template:FAQ Template:FAQ

Template:FAQ

Template:FAQ

Template:FAQ

Template:FAQ

优化

systemd-analyze

Systemd provides a tool called systemd-analyze that allows you to analyze your boot process so you can see which unit files are causing your boot process to slow down. You can then optimize your system accordingly. You have to install python-dbus and python-cairo to use it.

To see how much time was spent in kernel-/userspace on boot, simply use:

systemd-analyze
Tip: If you add the timestamp hook to your HOOKS array in /etc/mkinitcpio.conf and rebuild your initramfs, systemd-analyze will also be able to show you how much time was spent in the intramfs.

To list the started unit files, sorted by the time each of them took to start up:

systemd-analyze blame

You can also create a SVG file which describes your boot process grapically, similiar to Bootchart:

systemd-analyze plot > plot.svg

使用 bootchart

You can use a version of bootchart to visualize the boot sequence. Since you are not able to put a second init into the kernel cmdline you won't be able to use any of the standard bootchart setups. However the bootchart2AUR package from AUR comes with an undocumented systemd service. After you've installed bootchart2 do:

# systemctl enable bootchart.service

Read the bootchart documentation for further details on using this version of bootchart.

shell 短命令

Systemd daemon management requires a bit more text entry to accomplish tasks such as start, stopped, enabling, checking status, etc. The following functions can be added one's ~/.bashrc to help streamline interactions with systemd and to improve the overall experience.

if ! systemd-notify --booted; then  # not using systemd
  start() {
    sudo rc.d start $1
  }

  restart() {
    sudo rc.d restart $1
  }

  stop() {
    sudo rc.d stop $1
  }
else
  start() {
    sudo systemctl start $1.service
  }

  restart() {
    sudo systemctl restart $1.service
  }

  stop() {
    sudo systemctl stop $1.service
  }

  enable() {
    sudo systemctl enable $1.service
  }

  status() {
    sudo systemctl status $1.service
  }

  disable() {
    sudo systemctl disable $1.service
  }
fi

精简输出信息

Change verbose to quiet on the kernel line in GRUB. For some systems, particularly those with an SSD, the slow performance of the TTY is actually a bottleneck, and so less output means faster booting.

Early start

One central feature of systemd is dbus and socket activation, this causes services to be started when they are first accessed, and is generally a good thing. However, if you know that a service (like console-kit) will always be started during boot, then the overall boot time might be reduced by starting it as early as possible. This can be achieved (if the service file is set up for it, which in most cases it is) by issuing:

# systemctl enable console-kit-daemon.service

This will cause systemd to start console-kit as soon as possible, without causing races with the socket or dbus activation.

自动挂载(automount)

The default setup will fsck and mount all filesystems before starting most daemons and services. If you have a large /home partition, it might be better to allow services that do not depend on /home to start while /home is being fsck'ed. This can be achieved by adding the following options to the fstab entry of your /home partition:

noauto,x-systemd.automount

This will fsck and mount /home when it is first accessed, and the kernel will buffer all file access to /home until it is ready.

If you have encrypted filesystems with keyfiles, you can also add the noauto parameter to the corresponding entries in /etc/crypttab. systemd will then not open the encrypted device on boot, but instead wait until it is actually accessed and then automatically open it with the specified keyfile before mounting it. This might save a few seconds on boot if you are using an encrypted RAID device for example, because systemd doesn't have to wait for the device to become available. For example:

/etc/crypttab
data /dev/md0 /root/key noauto

Readahead

systemd comes with its own readahead implementation, this should in principle improve boot time. However, depending on your kernel version and the type of your hard drive, your mileage may vary (i.e. it might be slower). To enable, do:

# systemctl enable systemd-readahead-collect.service systemd-readahead-replay.service

Remember that in order for the readahead to work its magic, you should reboot a couple of times.

User sessions

systemd can divide user sessions into cgroups. Add session optional pam_systemd.so to your relevant /etc/pam.d/ files (e.g., login for tty logins, sshd for remote access, kde for password kdm logins, kde-np for automatic kdm logins).

Before:

$ systemd-cgls systemd:/system/getty@.service
systemd:/system/getty@.service:
├ tty5
│ └ 904 /sbin/agetty tty5 38400
├ tty2
│ ├ 13312 /bin/login --
│ └ 15765 -zsh
[…]

After:

$ systemd-cgls systemd:/user/example/
systemd:/user/example/:
├ 4
│ ├   902 /bin/login --
│ └ 16016 -zsh
[…]

Further, you can replace ConsoleKit's functionality with systemd. To do this, polkit needs to be rebuilt from ABS with systemd enabled (--enable-systemd), and stuff like USB automounting will work without consolekit. DBus supports systemd since version 1.6.0, so there's no longer need to build it from Git.

Troubleshooting

Shutdown/Reboot takes terribly long

If the shutdown process takes a very long time (or seems to freeze) most likely a service not exiting is to blame. systemd waits some time for each service to exit before trying to kill it. To find out if you are affected see this article in the fedora wiki.

SLiM and xfce-session

One setup that can produce a shutdown freeze is Xfce in conjunction with SLiM: Shutting down/rebooting using xfce-session will cause slim.service to hang for half a minute until systemd kills it the hard way. One workaround is to create a modified slim.service:

/etc/systemd/system/slim.service
[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]
WantedBy=graphical.target

This causes SLiM to be terminated using SIGKILL. Since the lock file is also removed this does not cause a problem.

See also