树莓派:文件系统写入文件,但重启后旧数据重新出现。

好的,这是一个在两个树莓派系统上出现的非常奇怪的问题,它们分别使用8GB的SD存储卡:
简单的例子: 当我将文件写入磁盘时,看起来文件已经被写入。 我可以编辑一个文件vim test.dat,输入文本并保存。 ll命令会列出该文件。 cat命令会显示文件的内容。 但是在重新启动后,文件就会消失。
所以我认为的情况是,Ubuntu将文件写入了Ubuntu的磁盘缓存,但没有将文件提交到磁盘。用户空间程序可以继续读取文件并使用它们,但缓存会从内存中返回目录列表和文件内容,而不是从磁盘中返回。因为在重新启动后,磁盘上没有任何新数据。
另一个例子:
dd if=/dev/zero of=testfile.dat bs=1M count=1000

创建一个大小为1GB的文件。 ll列出该文件。 df -h显示磁盘上的数据使用了1GB的空间。 但是在重新启动后,该文件消失了,df -h显示旧的可用空间。
有趣的事实:我知道SD卡的最大写入速度是9MB/秒,当我使用笔记本电脑将磁盘映像dd到SD卡时,我得到的速度就是这个。但是在树莓派上运行这个dd命令时,dd报告的写入速度是110MB/秒。这是不可能的。这就是为什么我认为操作系统只是写入内存而不是写入磁盘的原因。
第三个例子: 我有一个编辑名为interfaces的文件的脚本,然后以root身份将其复制到/etc/network/interfaces文件中,以更改设备的IP。然后脚本重新启动。
#!/bin/bash
cp /var/project/scripts/interfaces /etc/network/interfaces
/sbin/reboot

在重新启动后,设备仍然使用旧的IP地址... 奇怪...
第四个例子: 树莓派运行着一个Percona数据库。我有一个包含186条记录的表。我清空了这个表。用PHP代码和Webmin查看数据,表格是空的,就像应该的那样。但是在重新启动后,数据又回来了。真的... 186条记录。这让我感到很困惑。
我可能完全错了。有什么想法吗?
我一直在处理这个Ubuntu安装,并在每次重要软件更新后通过克隆磁盘映像进行定期备份。我注意到一些奇怪的事情(比如运行我的脚本后IP没有改变),但直到今天才意识到这个问题,似乎我所有克隆的磁盘映像都存在这个问题。它在某个时候肯定正常工作过,然后在树莓派上的Ubuntu出了问题...
问题是:我该怎么做才能让Ubuntu写入SD卡?

当我意识到文件没有写入SD卡时,我首先怀疑的是SD卡有问题。所以我打开了另一台运行着旧版本Ubuntu安装的树莓派,并且使用它自己的SD卡,结果出现了完全相同的问题! - Francois Stark
你从哪里获取Ubuntu的安装程序?我之前在我的Beaglebone上看到一些可用的镜像是作为RAM文件系统启动的,因此任何更改都不会永久保存。你能做其他的更改吗?如果你使用apt-get安装了一些东西,重启后是否会保留? - seanlano
从https://wiki.ubuntu.com/ARM/RaspberryPi安装。我已经在这个安装上工作了一年多。安装了Percona数据库、php、cakephp、蓝牙堆栈、nodejs、apache、hostapd等等。所有的安装和数据更新在这段时间内都完美运行。但是在某个阶段,它停止了向磁盘写入数据。 - Francois Stark
如果我无法解决文件写入问题,我想我的下一步就是使用厨师从头开始安装,以创建一个可复制的稳定安装。但考虑到所有已经投入其中的组件,你可以理解那将是很多工作。 - Francois Stark
AppArmor可能导致这个问题吗? - Francois Stark
我真的不确定,恐怕不是这样的。如果是AppArmor的话,那么根本就不允许写入任何内容。 - seanlano
今天,我找到了一张可以正常写入磁盘的三个月大的SD卡/设备。我重新完成了其中缺失的开发工作,并正在将其克隆到表现出这种奇怪丢失写入行为的设备的SD卡上。我会在有更多信息时发布更新。 - Francois Stark
你使用的文件系统是什么?我在我的SD卡的FAT32分区上遇到了类似的问题,这与SD卡无关。 - Sebastian
3个回答

使用sync命令似乎对我有所帮助。
sync

来自帮助:

强制将更改的块写入磁盘,更新超级块。

换句话说,它会刷新文件系统缓冲区。 然而,我会期望当你进行适当的 sudo reboot 而不是像我一样时,这将不是问题,因此同步可能对你没有作用。

我在一个树莓派 wheezy 安装中遇到了类似的问题。 它有一个包含只读文件系统的 ext4 分区。还有一个包含一些配置文件的 FAT32 可读写分区。当我更改了配置文件并拔掉电源插头重启后,更改并不会持久化。(请注意:如果没有只读的 Pi,在未安全关闭的情况下拔掉电源插头不是明智之举)



我遇到了完全相同的问题。我通过以下步骤解决了这个问题:
  • 步骤1:观察在/boot/cmdline.txtroot=PARTUUID=之后指定的值:

    cat /boot/cmdline
    

    在我的情况下,我找到了类似于093bedcc-02的内容:

    boot=overlay console=tty1 root=PARTUUID=093bedcc-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
    
  • 步骤2:使用lsblk查找前一步中root=PARTUUID=指定值的路径(更多详细信息请阅读man lsblk以格式化输出):

    lsblk -o NAME,FSTYPE,LABEL,UUID,PARTUUID,MOUNTPOINT,PATH
    

    在我的情况下,我得到了以下结果:

    NAME        FSTYPE LABEL  UUID                                 PARTUUID                             MOUNTPOINT PATH
    mmcblk0                                                                                                        /dev/mmcblk0
    ├─mmcblk0p1 vfat   boot   BC50-2AE4                            093bedcc-01                          /boot      /dev/mmcblk0p1
    └─mmcblk0p2 ext4   rootfs 9b87f948-9dc3-49e7-94fc-309bfabb1ac4 093bedcc-02                          /          /dev/mmcblk0p2
    

    在我的情况下,我得到了/dev/mmcblk0p2作为路径的值。

  • 步骤3:现在用其路径值(在我的情况下是/dev/mmcblk0p2)替换root=PARTUUID=,并在前面加上root=

    root=/dev/mmcblk0p2
    
  • 步骤4:最后使用以下命令重新启动系统:

    sudo reboot
    

1你能解释一下你在做什么以及它是如何解决问题的吗?我想要理解你的解决方案。 - Martin Fürholz
1@MartinFürholz,我试图编辑我的RPi的SD卡上的一个文件。在编辑完文件后,我将文件保存到了SD卡中。除非系统重新启动,否则RPi会保留该文件的更改。但由于某种原因,这些更改消失了。我不知道这些更改是否保存在RAM/缓存内存中。然而,我已经修改了root分区参数root=PARTUUID=093bedcc-02root=/dev/mmcblk0p2并重新启动了系统。之后系统正常运行。 - testuser