背景
某台 Arch Linux KDE Plasma 桌面系统在登录后检查用户级 systemd 服务状态时,发现曾经出现过 Akonadi 相关失败记录。Akonadi 是 KDE PIM 体系中的个人信息管理后端,常被 KMail、Kontact、KOrganizer、KAddressBook、日历提醒、联系人、邮件索引等组件使用。
问题的表面现象比较迷惑:
systemctl --user --failed --no-pager
一开始能看到 Akonadi 相关失败;但随后执行:
akonadictl status
又显示:
Akonadi Control: running
Akonadi Server: running
也就是说,systemd 认为某次 Akonadi 启动失败了,但 Akonadi 本身后来又确实运行起来了。
这类问题如果直接重建 Akonadi 数据库,很容易扩大风险。更合理的处理方式是先确认失败链路,再做最小可回退修复。
初始现象
用户级日志中可以看到类似记录:
Starting Akonadi Control...
akonadiserver: Starting up the Akonadi Server...
akonadi_control.service: start operation timed out. Terminating.
akonadi_control.service: Killing process ... (mysqld) with signal SIGKILL.
akonadi_control.service: Failed with result 'timeout'.
Failed to start Akonadi Control.
Akonadi 使用内置 MariaDB/MySQL 后端。日志中 mysqld 被 systemd 杀掉,说明失败并不是单纯的前端组件问题,而是 Akonadi 启动流程中包含的数据库进程被一并终止了。
系统级 unit 内容类似:
[Service]
ExecStart=/usr/bin/akonadi_control
Type=dbus
BusName=org.freedesktop.Akonadi.Control
TimeoutSec=5sec
Slice=background.slice
Restart=no
最初可疑点是 TimeoutSec=5sec。Akonadi 登录阶段启动时需要拉起 MariaDB、初始化数据库、注册 D-Bus 名称。5 秒确实偏紧。
第一轮修正:把 TimeoutSec 临时改为 30 秒
为了确认是否只是 5 秒太短,使用用户级 systemd drop-in 覆盖配置,而不是修改 /usr/lib/systemd/user/akonadi_control.service 原文件。
执行:
systemctl --user edit akonadi_control.service
写入:
[Service]
TimeoutSec=30sec
然后:
systemctl --user daemon-reload
systemctl --user show akonadi_control.service -p TimeoutStartUSec -p TimeoutStopUSec
确认变为:
TimeoutStartUSec=30s
TimeoutStopUSec=30s
手动 stop/start 测试中,Akonadi 可以正常启动:
akonadictl stop
akonadictl start
akonadictl status
日志显示:
Akonadi server is now operational.
Started Akonadi Control.
这说明 Akonadi 数据库本身不是彻底损坏状态。
重新登录后问题仍然复现
重新登录后,问题再次出现,但时间点变成了 30 秒:
Starting Akonadi Control...
30 秒后 start operation timed out
随后 stop-sigterm timed out
systemd 杀掉 akonadi_control 和 mysqld
Failed with result 'timeout'
这一步非常关键。它说明:
- 30 秒 override 已经生效;
- 问题不是简单的“5 秒太短”;
- 登录阶段第一次启动存在更深层的卡住或竞态。
更奇怪的是,失败后 Akonadi 又运行起来了:
akonadictl status
显示:
Akonadi Control: running
Akonadi Server: running
但:
systemctl --user status akonadi_control.service
却显示:
Active: inactive (dead)
这说明当前运行中的 Akonadi 实例不一定属于 akonadi_control.service 这个 unit 管理。
关键诊断:当前 Akonadi 挂在 kalendarac 的 app slice 下
进一步检查进程、cgroup 和 D-Bus owner:
pgrep -a -f 'akonadi|mysqld.*akonadi'
ps -o pid,ppid,stat,etime,cmd -C akonadi_control -C akonadiserver -C mysqld
busctl --user status org.freedesktop.Akonadi.Control
systemd-cgls --user | grep -A20 -B10 -Ei 'akonadi|mysqld'
结果显示:
akonadi_control.service自身已经 failed 或 inactive;- 当前活着的 Akonadi 进程属于
app-org.kde.kalendarac@autostart.service; org.freedesktop.Akonadi.Control当前 D-Bus owner 也指向这个后起实例;kalendarac是 KDE Calendar Reminders 组件,会在登录时自启动。
由此可以还原真实链路:
KDE 登录
↓
kalendarac 自动启动
↓
kalendarac 过早触发 Akonadi
↓
systemd --user 同时尝试通过 akonadi_control.service 启动 Akonadi
↓
启动路径发生竞态
↓
systemd 管理的那次 akonadi_control.service 超时失败
↓
mysqld 被强杀
↓
随后 Akonadi 又通过 kalendarac 相关路径重新起来
↓
Akonadi 实际可用,但 systemd 留下 failed 记录
这解释了为什么会同时出现:
systemctl 显示 Akonadi failed / inactive
akonadictl 显示 Akonadi running
为什么不重建 Akonadi 数据库
MariaDB 日志中虽然出现过 crash recovery:
Recovering after a crash using tc.log
Crash table recovery finished.
ready for connections.
但这不是数据库已经损坏的证据,而是因为前一次 mysqld 被 systemd SIGKILL 强杀,下一次启动时自然会做恢复。
排查中没有发现:
schema corruption
permission denied
root-owned 文件
socket 权限异常
lock 文件残留导致无法启动
持续崩溃循环
所以没有理由重建:
~/.local/share/akonadi
~/.config/akonadi
直接删除或重建 Akonadi 数据库属于高风险绕路,不是本次问题的根本修复。
最小可回退修复:禁用当前用户的 kalendarac 自启动
既然根因指向 kalendarac 登录早期触发 Akonadi,那么修复方向应当是切断这个过早触发源,而不是继续扩大 timeout。
系统级 autostart 文件位于:
/etc/xdg/autostart/org.kde.kalendarac.desktop
不修改系统级文件,而是在当前用户目录创建 shadow 文件:
~/.config/autostart/org.kde.kalendarac.desktop
内容基于系统级文件复制,并在末尾追加:
Hidden=true
这样只会禁用当前用户的 Calendar Reminders 登录自启动。回退方式也很简单:删除这个用户级 shadow 文件即可。
该修复不会:
卸载 KDE PIM
禁用 Akonadi
删除数据库
修改 /usr/lib
修改 /etc
mask systemd service
它只是让 kalendarac 不再登录时过早启动。
撤销临时 30 秒 override
在禁用 kalendarac 后重新登录,Akonadi 已经可以正常启动。此时可以撤销之前的 30 秒 timeout 临时修正,让 akonadi_control.service 回到系统默认 5 秒。
建议不要直接删除,先改名备份:
mv -v ~/.config/systemd/user/akonadi_control.service.d/override.conf \
~/.config/systemd/user/akonadi_control.service.d/override.conf.disabled-$(date +%Y%m%d-%H%M%S)
然后:
systemctl --user daemon-reload
确认恢复默认:
systemctl --user show akonadi_control.service -p TimeoutStartUSec -p TimeoutStopUSec
预期:
TimeoutStartUSec=5s
TimeoutStopUSec=5s
最终验证
重启或重新登录后执行:
systemctl --user --failed --no-pager
结果:
0 loaded units listed.
查看 Akonadi 日志:
journalctl --user -b -u akonadi_control.service --no-pager -o short-iso | grep -Ei 'Starting|Started|operational|timeout|Failed|Killing'
正常结果类似:
Starting Akonadi Control...
Starting up the Akonadi Server...
Akonadi server is now operational.
Started Akonadi Control.
没有再出现:
start operation timed out
Killing process ... mysqld
Failed to start Akonadi Control
Failed with result 'timeout'
检查进程:
pgrep -a -f 'kalendarac|akonadi|mysqld.*akonadi'
结果中没有 kalendarac,但 Akonadi 可以正常运行:
/usr/bin/akonadi_control
/usr/bin/akonadiserver
/usr/bin/mysqld --defaults-file=...
这说明:
kalendarac自启动禁用生效;- Akonadi 不再被登录早期的日历提醒组件制造竞态;
akonadi_control.service使用默认 5 秒 timeout 也能正常启动;- systemd 用户级失败列表保持干净。
关于日志中的 portal 警告
Akonadi 启动过程中仍可能出现:
Failed to register with host portal
Could not register app ID
这些属于 KDE/portal 相关警告噪音。只要后续出现:
Akonadi server is now operational.
Started Akonadi Control.
并且没有 timeout、SIGKILL、failed result,就不应把这些 portal 警告当作 Akonadi 启动失败处理。
结论
本次故障的根因不是 Akonadi 数据库损坏,也不是 MariaDB 无法启动,而是 KDE 登录阶段 kalendarac 自动启动过早触发 Akonadi,造成 akonadi_control.service 的 systemd/DBus 启动路径发生竞态。
最终有效修复是:
禁用当前用户的 kalendarac 自启动
保留 Akonadi 正常按需启动
撤销临时 TimeoutSec=30sec override
不重建数据库
不卸载 KDE PIM
不修改系统级 unit
最终系统状态:
systemctl --user --failed → 0 failed units
akonadi_control.service → 正常启动
kalendarac → 当前用户不再登录自启
Akonadi 数据库 → 保持原状
TimeoutSec → 恢复系统默认 5 秒
这类 KDE PIM 问题最容易被误判为“数据库坏了”。实际排查中,应优先区分三件事:
Akonadi 本体是否可启动
systemd unit 是否管理当前实例
登录阶段是否有其他组件过早触发 Akonadi
只有确认存在数据库损坏、权限错误或 schema 错误时,才应考虑重建 Akonadi 数据库。否则,最小可回退修复通常更安全。