疑难解答

寻找错误

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

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

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

或者使用 systemd 消息:

  1. $ journalctl -fp err

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

  1. $ systemctl status systemd-modules-load
  1. systemd-modules-load.service - Load Kernel Modules
  2. Loaded: loaded (/usr/lib/systemd/system/systemd-modules-load.service; static)
  3. Active: failed (Result: exit-code) since So 2013-08-25 11:48:13 CEST; 32s ago
  4. Docs: man:systemd-modules-load.service(8).
  5. man:modules-load.d(5)
  6. 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):

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

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

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

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

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

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

  1. # systemctl start systemd-modules-load

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

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

  1. $ systemctl status systemd-modules-load
  1. systemd-modules-load.service - Load Kernel Modules
  2. Loaded: loaded (/usr/lib/systemd/system/systemd-modules-load.service; static)
  3. Active: active (exited) since So 2013-08-25 12:22:31 CEST; 34s ago
  4. Docs: man:systemd-modules-load.service(8)
  5. man:modules-load.d(5)
  6. Process: 19005 ExecStart=/usr/lib/systemd/systemd-modules-load (code=exited, status=0/SUCCESS)
  7. 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 服务的工作状况不合预期,希望调试的话,设置 SYSTEMDLOG_LEVEL 环境变量debug . 例如以调试模式运行 _systemd-networkd 服务:

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

  1. [Service]
  2. Environment=SYSTEMD_LOG_LEVEL=debug

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

  • SYSTEMDLOG_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。

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

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

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

然后运行:

  1. # /usr/lib/systemd/systemd-sysctl

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

  1. $ 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 模式会导致系统无法远程连接,可以通过下面方式禁用紧急模式:

  1. # systemctl mask emergency.service
  2. # systemctl mask emergency.target