[博客翻译]使用只读根文件系统运行Raspberry Pi


原文地址:https://www.dzombak.com/blog/2024/03/Running-a-Raspberry-Pi-with-a-read-only-root-filesystem.html


许多在 Raspberry Pi 和类似单板计算机上运行的应用程序——比如将数据报告到中心数据库服务器的环境数据记录器——实际上并不需要在 Pi 的 SD 卡上本地存储任何状态。这意味着你可以使用只读根文件系统运行 Pi,这样可以极大地延长 SD 卡的使用寿命。

请记住,在只读文件系统下,重启或电源故障后,日志不会在 Pi 上持久保存,因此远程日志对于故障排查非常有帮助。本文中的信息截至2024年3月,至少适用于Raspberry Pi OS 11(Bullseye)和12(Bookworm),但不作任何保证。

这些更改风险较高;即使一切顺利,按照步骤操作也可能导致 Pi 无法启动,需要通过键盘和显示器进行修复(参阅我的《Pi 可靠性》一文中的风险与收益)。microSD卡选择 对于这种情况,使用最小的 SD 卡即可;高级耐用卡虽然理想但并非强制,因为目标是(几乎)不写入它。

操作概述:主要步骤包括:

3.png

  1. 移除不必要的软件并禁用不必要的服务
  2. 确保 Pi 不使用 SD 卡作为交换空间
  3. 对于依赖于写入磁盘的服务,采取工作变通或黑客手段
  4. 为必须可写入的路径提供 tmpfs 文件系统,存储临时数据
  5. 配置系统以将根文件系统设置为只读
  6. 在系统范围内添加 shell 简捷方式以简化系统维护

详细步骤如下:

  1. 移除不必要的软件和服务:尽管有些指南建议移除 logrotate 并使用 busybox-syslogd 替代,但我倾向于继续使用 journalctl,因此不做此操作。检查 Pi 上运行的服务,并禁用不需要的,并确保 Pi 不使用 SD 卡作为交换空间。
  2. 更新并重启:虽然不是必需的,但我喜欢在冻结系统之前确保其是最新的:sudo apt update && sudo apt upgradesudo apt autoremove --purgesudo reboot now
  3. 编辑 /boot/cmdline.txt:禁用交换空间和文件系统检查,添加 fsck.mode=skip noswap(除非计划使用外部驱动作为交换空间)
  4. 转换到 NTP 而不是 systemd-timesyncd:根据网络资料,systemd-timesyncd 在只读文件系统下可能无法工作,但我们可以使用 NTP,并允许 fake-hwclock 写入文件系统(尽管这不理想),但每次开机时时钟都会重置到1970年,这会导致问题。同时,使用 sudo raspi-config 检查时间设置是否正确。
  5. 从 systemd-timesyncd 切换到 NTP:sudo systemctl disable systemd-timesyncd.servicesudo apt install ntp,然后调整 NTP 设置,如编辑 /etc/ntp.conf 并将 driftfile 设置到临时文件夹 /var/tmp(稍后将放入 tmpfs)。
  6. 网络管理:这些步骤适用于 Raspberry Pi OS 11、12 及更高版本。对于较旧版本(10/Buster 及以下),请参阅我先前博客中的 DHCP/DHCPD5 部分。
  7. 重新排列网络文件:移除不必要的持久文件,并在 /var/run(已为 tmpfs)创建链接:sudo mv /etc/resolv.conf /var/run/resolv.conf && sudo ln -s /var/run/resolv.conf /etc/resolv.conf 等。
  8. 移动随机种子文件到可写位置:将现有的 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
  9. 针对 snapd:我对只读文件系统上的 snapd 行为了解有限,但目前注意到:通过 snap 安装的程序似乎仍能运行,但会有一些日志消息(如无法运行守护进程等),但这些可以忽略,因为 snapd 无法写入 state.json 时无需保持锁。
  10. 关闭 systemd-rfkill:虽然不多见讨论,但在无线设备(Wi-Fi、蓝牙)正常工作的情况下,可以禁用此服务:sudo systemctl disable systemd-rfkill.servicesudo systemctl mask systemd-rfkill.socket
  11. 禁用每日 apt 和 mandb 任务:这些任务期望在重启后写入持久文件系统,但在冻结软件的系统中不需要:sudo systemctl mask man-db.timer 等。
  12. 将临时文件夹移到 tmpfs:编辑 /etc/fstab 添加临时文件系统条目。
  13. 移动 spool 文件夹到 tmpfs:编辑 /etc/fstab 添加 spool 文件夹条目(如 /var/spool/mail/var/spool/rsyslog)。
  14. 处理 /var/log:在 /etc/fstab 中添加 /var/log 的 tmpfs 条目,并限制 journald 的空间使用(如果使用 journald)。
  15. 可选:完全禁用 journald 持久化:如果不希望将 /var/log 存储在 RAM 中或磁盘上,可以配置系统不写入日志到这些位置。
  16. 重启、检查并修复:重启系统后,通过 mount 命令验证 SD 卡分区是否为只读模式,并使用 sudo journalctl -b 0 检查是否有任何问题。