openSUSE:Systemd 侦错

跳转至: 导航, 搜索

openSUSE 的开机速度有时会不尽如人意。本文介绍了如何使用 Systemd 优化开机速度的内容。

systemd-analyze 安装

sudo zypper in systemd-analyze

The "Blame" Game

优化前我们需要先来玩一场「推诿」的游戏,就是看看是哪个 service 占用了最多的开机时间。

systemd-analyze blame | head

systemd-analyze blame 是把服务按运行时间的长短排序,最长的在最上面。head 是返回时间最长的 10 个,如:

238588ms systemd-tmpfiles-setup.service
3037ms NetworkManager.service
1953ms avahi-daemon.service
1762ms systemd-logind.service
1686ms postfix.service
1255ms fglrxrebuild.service
1132ms systemd-vconsole-setup.service
1071ms systemd-udev-root-symlink.service
974ms cycle.service
931ms dev-mqueue.mount

更加先进的还有:

systemd-analyze plot > systemd.svg

这将生成一个 svg 图片,告诉你哪些服务是并行启动的,它们又占用了多长时间。

注意: 首先这里是以毫秒计算的,所以不要以为 931ms 很长。基本上如果这个数字不过「万」,比如 38588ms,是没有优化的必要的; 其次 systemd 是并行启动,所以最终的开机时间不是这些数字的简单相加。它们之间是可能有重叠的部分的,最终的开机时间要看 plot 图。

揪出元凶

知道了哪个服务慢是不够的,你还要知道那个服务为什么慢。所以就因服务而异了。

如果你耗时的服务是如 NetworkManager.service 这种自身提供了日志的程序,那么去 /var/log 检查它的日志。否则你要用到 strace。

strace 大显神威

首先我们要去 /usr/lib/systemd/system 下找到耗时的 .service 文件,把它复制到 /etc/systemd/system。这一过程又叫做 mask(遮挡),因为对 systemd 来说,/usr/lib/systemd/system 是给发行版用的,/etc/systemd/system 是给系统管理员用的。后者的优先级比前者高(便于管理),这样 /etc 里有同名服务,就不会去跑 /usr 里的服务,于是 /usr 里的服务就被「遮挡」掉了。

下面打开那个服务,查找 ExecStart= 这行:

ExecStart=/usr/bin/systemd-tmpfiles --create --remove

在前面加上 /usr/bin/strace -f -tt -o /var/run/%N.strace,变成:

ExecStart=/usr/bin/strace -f -tt -o /var/run/%N.strace /usr/bin/systemd-tmpfiles --create --remove

重启。

这时遮挡生效,于是 /var/run 里有了一个 systemd-tmpfiles-setup.strace 的文本文件,内容是 strace 记录的 /usr/bin/systemd-tmpfiles 进行的磁盘读写、打开文件等操作。

打开它,找出耗时最长的操作,如:

463   19:37:42.939174 getdents(4, /* 586 entries */, 32768) = 32752
463   19:41:39.007576 getdents(4, /* 585 entries */, 32768) = 32760

我们可以看出将近 4 分钟的时间里,这个 service 只干了一件事,那就是:

getdents(4, /* 586 entries */, 32768)

于是我们要去 google 这个操作究竟是干嘛的。

getdents - get directory entries

它一直在获取某个文件夹。究竟获取哪个文件夹呢?

21124 21:47:35.935581 openat(AT_FDCWD, "/home/marguerite/Documents/KDE", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
21124 21:47:35.935662 getdents(3, /* 26 entries */, 32768) = 832
21124 21:47:35.935776 getdents(3, /* 0 entries */, 32768) = 0

在它最上访的 openat 函数的第二个参数说明了这个文件夹的路径。

于是问题找到。可能是你的某个 tmp 文件夹太大(好长时间没清理了),或者是权限不对(没有读取权限)之类的。相应找方法处理下(用 tmpwatch 啊,chmod 啊之类的)。

重启。再用 systemd-analyze blame | grep systemd-tmpfiles-setup.service 查看:

222ms systemd-tmpfiles-setup.service

成功!

这时删除掉我们之前进行的遮挡:

sudo rm -rf /etc/systemd/system/systemd-tmpfiles-setup.service

收工!

参考链接

作者

MargueriteSu 2013年6月25日 (二) 08:30 (MDT)