7.10. systemd 的用法与配置

7.10.1. 基础配置

/etc/systemd/system.conf 文件包含了大量的 systemd 控制命令。 假如未作任何的更改,文件中的所有行应该都是注释掉的,这代表了 systemd 正使用默认的运行方式。 这个文件中可以设置日志级别,可以修改日志的基本设置。所有设置项都可以在 man 手册的 systemd-system.conf(5) 中查看。

7.10.2. 禁用启动时清屏

默认情况下,systemd 将会在系统启动快要结束的时候清屏。如不需要,使用以下操作禁用:

mkdir -pv /etc/systemd/system/getty@tty1.service.d

cat > /etc/systemd/system/getty@tty1.service.d/noclear.conf << EOF
[Service]
TTYVTDisallocate=no
EOF

拥有 root 权限的账户可以通过 journalctl -b 查看启动信息。

7.10.3. 禁止 /tmp 使用 tmpfs

默认情况下,/tmp 使用 tmpfs 文件系统。如不需要,使用以下操作禁用:

ln -sfv /dev/null /etc/systemd/system/tmp.mount

或许,如果你需要一个单独的 /tmp 分区,那请在 /etc/fstab 条目中指定该分区。

[警告]

警告

如果使用的是独立的 /tmp 分区,就不要创建上述链接。这将保护根(/)文件系统,使其在重新挂载后失去 r/w 权限,从而导致系统在启动后无法使用。

7.10.4. 配置自动创建和删除文件

有这样几个服务可以建立或删除文件/目录:

  • systemd-tmpfiles-clean.service

  • systemd-tmpfiles-setup-dev.service

  • systemd-tmpfiles-setup.service

系统配置文件在 /usr/lib/tmpfiles.d/*.conf 中。 本地配置文件在 /etc/tmpfiles.d 中。 /etc/tmpfiles.d中的文件会覆盖 /usr/lib/tmpfiles.d 中相同名称的文件。 (译者注:首先读取系统范围配置文件,再读取用户范围配置文件,用户范围配置文件会覆盖系统范围配置文件的相同部分。)可以在 man 手册的 tmpfiles.d(5) 中获取文件格式详情。

注意,/usr/lib/tmpfiles.d/*.conf 文件的语法比较容易搞错。例如,默认对于 /tmp 目录下文件的删除,源自 /usr/lib/tmpfiles.d/tmp.conf 中的这一行:

q /tmp 1777 root root 10d

类型字段 q,用于创建带配额的子卷,仅适用于 btrfs 文件系统。它会引用类型 v,然后引用类型 d (目录)。然后创建指定的目录,如果它原先不存在的话,并为其调整权限,指定所有权。

如果默认参数不能达到要求,那就复制文件至 /etc/tmpfiles.d 按照自己的需求修改它。复制示例:

mkdir -p /etc/tmpfiles.d
cp /usr/lib/tmpfiles.d/tmp.conf /etc/tmpfiles.d

7.10.5. 覆盖默认服务的行为

可以通过在 /etc/systemd/system 中创建目录和配置文件来覆盖单元的参数。例如:

mkdir -pv /etc/systemd/system/foobar.service.d

cat > /etc/systemd/system/foobar.service.d/foobar.conf << EOF
[Service]
Restart=always
RestartSec=30
EOF

可以在 man 手册的 systemd.unit(5) 中查询更多信息。创建好文件之后,请运行 systemctl daemon-reloadsystemctl restart foobar 激活所做更改。

7.10.6. 调试启动顺序

相较于 SysVinit 或 BSD 风格的初始化使用的是简单的 shell 脚本,而 systemd 对于不同类型的启动文件(或单元)使用的是统一的格式。systemctl 命令可用于用于,启用,禁用,控制状态,和获取单元文件的状态。以下是一些常用命令的示例:

  • systemctl list-units -t <service> [--all]:列出加载的服务类型的单元文件。

  • systemctl list-units -t <target> [--all]:列出加载的目标类型的单元文件。

  • systemctl show -p Wants <multi-user.target>:显示所有依赖多用户的目标。目标是与 SysVinit 运行级不同的特殊单元文件。

  • systemctl status <servicename.service>:显示服务名称服务的状态。扩展名 .service 在没有同名单元文件,例如 .socket(创建监听套接字功能与 inetd/xinetd 相似的)文件,的情况下可以省略。

7.10.7. 使用 systemd 日志

systemd 启动的系统上的日志记录(默认)由 systemd-journald 处理的,而不是传统的 unix syslog 守护程序。如果需要,你也可以添加 syslog 的守护进程与之并行运作。systemd-journald 程序使用二进制形式存储日志条目而非纯文本的日志文件。为了帮助解析文件,提供了 journalctl 命令。以下是一些常用命令的示例:

  • journalctl -r:按时间逆序现实所有的内容。

  • journalctl -u UNIT:显示与指定 UNIT 相关的日志条目。

  • journalctl -b[=ID] -r:按时间逆序显示自上次成功启动(或启动 ID)的日志条目。

  • journalctl -f:提供类似与 tail -f (follow) 类似的功能。

7.10.8. 长时间运行进程

自 systemd-230 开始,用户的所有进程都会随着用户会话的结束而被杀死,即使你用了 nohup,或进程使用了 daemon() 或是 setsid() 功能。这是为了是让原先宽松的环境变得更为严格而故意为之的。如果你依赖长时间运行的程序(例如,screen 或是 tmux),需要在你结束用户会话后保持运作。有三个方法能让进程保持在用户会话结束后仍然逗留。

  • 仅为需要的用户启用进程逗留:正常用户有权使用命令 loginctl enable-linger 来为其启用进程逗留。系统管理员可以使用相同的命令伴随着 user 参数,来帮某个用户实现。用户可以在之后使用命令 systemd-run 来启动长时间运行进程。举个例子:systemd-run --scope --user /usr/bin/screen。如果你为你的用户启用了逗留,user@.service 会在所有的登录会话被关闭后仍然保留,并在系统启动后自动启动。这样做的好处是明确地表明是否允许进程在用户会话结束后继续运行,但却打破了对于类似于 nohup 之类工具和使用 deamon() 的公用方法的向后兼容。

  • 启用系统范围的进程逗留:你可以在 /etc/logind.conf 中设置 KillUserProcesses=no 来全局地为每个用户启用进程逗留。这在牺牲明确控制的同时,带来了将旧方法提供给所有用户的好处。

  • 在构建时禁用:你可以通过在构建 systemd 时向命令 meson 添加 -Ddefault-kill-user-processes=no,以此来默认启用逗留。这会使 systemd 完全丧失在用户会话结束后杀死进程的能力。