许多在 Raspberry Pi 和类似单板计算机上运行的应用程序——比如将数据报告到中心数据库服务器的环境数据记录器——实际上并不需要在 Pi 的 SD 卡上本地存储任何状态。这意味着你可以使用只读根文件系统运行 Pi,这样可以极大地延长 SD 卡的使用寿命。
请记住,在只读文件系统下,重启或电源故障后,日志不会在 Pi 上持久保存,因此远程日志对于故障排查非常有帮助。本文中的信息截至2024年3月,至少适用于Raspberry Pi OS 11(Bullseye)和12(Bookworm),但不作任何保证。
这些更改风险较高;即使一切顺利,按照步骤操作也可能导致 Pi 无法启动,需要通过键盘和显示器进行修复(参阅我的《Pi 可靠性》一文中的风险与收益)。microSD卡选择 对于这种情况,使用最小的 SD 卡即可;高级耐用卡虽然理想但并非强制,因为目标是(几乎)不写入它。
操作概述:主要步骤包括:
- 移除不必要的软件并禁用不必要的服务
- 确保 Pi 不使用 SD 卡作为交换空间
- 对于依赖于写入磁盘的服务,采取工作变通或黑客手段
- 为必须可写入的路径提供 tmpfs 文件系统,存储临时数据
- 配置系统以将根文件系统设置为只读
- 在系统范围内添加 shell 简捷方式以简化系统维护
详细步骤如下:
- 移除不必要的软件和服务:尽管有些指南建议移除 logrotate 并使用 busybox-syslogd 替代,但我倾向于继续使用 journalctl,因此不做此操作。检查 Pi 上运行的服务,并禁用不需要的,并确保 Pi 不使用 SD 卡作为交换空间。
- 更新并重启:虽然不是必需的,但我喜欢在冻结系统之前确保其是最新的:
sudo apt update && sudo apt upgrade
,sudo apt autoremove --purge
,sudo reboot now
- 编辑 /boot/cmdline.txt:禁用交换空间和文件系统检查,添加
fsck.mode=skip noswap
(除非计划使用外部驱动作为交换空间) - 转换到 NTP 而不是 systemd-timesyncd:根据网络资料,systemd-timesyncd 在只读文件系统下可能无法工作,但我们可以使用 NTP,并允许 fake-hwclock 写入文件系统(尽管这不理想),但每次开机时时钟都会重置到1970年,这会导致问题。同时,使用
sudo raspi-config
检查时间设置是否正确。 - 从 systemd-timesyncd 切换到 NTP:
sudo systemctl disable systemd-timesyncd.service
,sudo apt install ntp
,然后调整 NTP 设置,如编辑/etc/ntp.conf
并将 driftfile 设置到临时文件夹/var/tmp
(稍后将放入 tmpfs)。 - 网络管理:这些步骤适用于 Raspberry Pi OS 11、12 及更高版本。对于较旧版本(10/Buster 及以下),请参阅我先前博客中的 DHCP/DHCPD5 部分。
- 重新排列网络文件:移除不必要的持久文件,并在
/var/run
(已为 tmpfs)创建链接:sudo mv /etc/resolv.conf /var/run/resolv.conf && sudo ln -s /var/run/resolv.conf /etc/resolv.conf
等。 - 移动随机种子文件到可写位置:将现有的 systemd 随机种子文件移动到 tmpfs 目录,并在原位置创建链接:
sudo mv /var/lib/systemd/random-seed /tmp/systemd-random-seed && sudo ln -s /tmp/systemd-random-seed /var/lib/systemd/random-seed
- 针对 snapd:我对只读文件系统上的 snapd 行为了解有限,但目前注意到:通过 snap 安装的程序似乎仍能运行,但会有一些日志消息(如无法运行守护进程等),但这些可以忽略,因为 snapd 无法写入
state.json
时无需保持锁。 - 关闭 systemd-rfkill:虽然不多见讨论,但在无线设备(Wi-Fi、蓝牙)正常工作的情况下,可以禁用此服务:
sudo systemctl disable systemd-rfkill.service
和sudo systemctl mask systemd-rfkill.socket
- 禁用每日 apt 和 mandb 任务:这些任务期望在重启后写入持久文件系统,但在冻结软件的系统中不需要:
sudo systemctl mask man-db.timer
等。 - 将临时文件夹移到 tmpfs:编辑
/etc/fstab
添加临时文件系统条目。 - 移动 spool 文件夹到 tmpfs:编辑
/etc/fstab
添加 spool 文件夹条目(如/var/spool/mail
和/var/spool/rsyslog
)。 - 处理
/var/log
:在/etc/fstab
中添加/var/log
的 tmpfs 条目,并限制 journald 的空间使用(如果使用 journald)。 - 可选:完全禁用 journald 持久化:如果不希望将
/var/log
存储在 RAM 中或磁盘上,可以配置系统不写入日志到这些位置。 - 重启、检查并修复:重启系统后,通过
mount
命令验证 SD 卡分区是否为只读模式,并使用sudo journalctl -b 0
检查是否有任何问题。