我想自动测试如果无法读取重要的 SQLite DB 文件(导致 I/O 错误),软件是否按预期做出反应。这正是几天前在客户那里发生的事情。我们手动修复了它,但现在我想创建自动代码来修复它,并且需要访问损坏的文件来测试它。
由于 Unix 中的所有内容都是文件,我怀疑可能有一个特殊的文件,当人们尝试读取它时,它总是会导致 I/O 错误(例如在 /dev 中)。
一些类似的文件(imo)是:
/dev/full
如果您尝试写入,它总是显示“设备上没有剩余空间”/dev/null
和/dev/zero
所以我认为只需要有一个这样的文件(但还没有找到)。
有谁知道这样的文件或任何其他方法可以让我获得所需的结果(故意错误的分区映像,使用 LD_PRELOAD 围绕 open() 的包装器,...)?
去这里最好的方式是什么?
答案1
Stack Overflow 和 Server Failure 上已经有很多关于这个问题的答案,但缺少一些技术。为了让生活更轻松,这里列出了 VM/Linux 块设备/Linux 文件系统/Linux 用户空间库 I/O 故障注入机制:
- 使用设备映射器的错误/片状的/延迟/DM-粉尘 从合成块设备返回错误/损坏或延迟/分割 IO 到合成块设备的设备(内核,需要使用设备映射器支持构建内核、适当的附加设备映射器模块(dm-dust 仅在内核 >=5.2 上可用)并拥有设备映射器用户空间位)。
- 使用md的性格有缺陷在合成块设备上执行周期性故障注入。请参阅
--layout
mdadm 手册页的选项了解如何配置它(内核和 mdadm 用户空间位)。 - 使用libfiu 对 POSIX API 调用执行故障注入 (用户空间,可与 一起使用
LD_PRELOAD
)。 - 使用Linux 内核的故障注入器将错误注入底层块设备 (内核,要求内核已使用 构建
FAIL_MAKE_REQUEST=y
)。 - 使用SystemTap进行故障注入(内核,需要使用内核构建很多东西)。
- 使用 CharybdeFS 注入文件系统故障或者佩塔德FS(通过 FUSE 的用户空间)。
- 使用以下命令创建合成块设备执行故障注入的 Linux scsi_debug 驱动程序(核心)。
- 在 QEMU 中运行您的系统并使用QEMU 使用 blkdebug 驱动程序注入块设备错误(虚拟机)。
- 通过以下方式创建合成块设备null_blk 设备注入故障的选项(内核 >= 4.14 但选项如超时概率直到 4.17 才出现,并且要求内核已使用
BLK_DEV_NULL_BLK_FAULT_INJECTION=y
) 构建。 - 创建一个综合网络块设备,通过以下方式向主机提供服务NBDkit 过滤器例如
delay
或者error
然后通过nbd-client
(内核 + NBD 用户空间位,内核 >= 4.18 内置 NBD 支持,nbdclient >= 3.18 和 nbdkit >= 1.8.1 推荐)将块设备连接到它 - 参见NBDKit 演示视频大约 20 分钟)。
额外事实:SQLite有一个VFS驱动程序用于模拟错误这样可以获得良好的测试覆盖率。
有关的:
答案2
您可以使用或目标dmsetup
来创建设备映射器设备来模拟故障。error
flakey
dmsetup create test --table '0 123 flakey 1 0 /dev/loop0'
其中 123 是设备的长度(以扇区为单位),/dev/loop0 是要在其上模拟错误的原始设备。对于错误,您不需要后续参数,因为它总是返回错误。
答案3
你想要一个故障注入I/O 机制。
在 Linux 上,这是一种不需要任何事先设置并生成异常错误的方法(不是 EIO“输入/输出错误”,而是 ESRCH“没有这样的进程”):
cat /proc/1234/mem
其中 1234 是与您正在测试的进程以同一用户身份运行的进程的 PID,但不是该进程本身。致谢鲁巴索夫为了思维的/proc/$pid/mem
。
如果您使用进程本身的 PID,您将获得 EIO,但前提是您正在从未映射到进程内存中的区域读取数据。第一页永远不会被映射,因此如果您按顺序读取文件是可以的,但不适合直接查找文件中间的数据库进程。
通过 root 身份进行更多设置,您可以利用设备映射器创建具有有效扇区和坏扇区的文件。
另一种方法是实施一个小型的保险丝文件系统。 EIO 是用户空间文件系统驱动程序出现错误时的默认错误代码,因此很容易实现。这俩珀尔和Python绑定附带了入门示例,您可以快速编写一个文件系统,该文件系统主要镜像现有文件,但在精心选择的位置注入 EIO。有一个现有的这样的文件系统:佩塔德夫斯(文章),我不知道它开箱即用的效果如何。
还有一种方法是LD_PRELOAD
包装纸。现有的一个是图书馆(用户空间中的错误注入)。它的工作原理是预加载一个重载 POSIX API 调用的库。您可以编写简单的指令或任意 C 代码来覆盖正常行为。
答案4
您可以使用专门为此目的而制作的 CharybdeFS。
它是一个类似于 PetardFS 的直通熔断文件系统,但可配置性更高。
请参阅此处的 CharybdeFS 食谱:http://www.scyladb.com/2016/05/02/fault-injection-filesystem-cookbook/
它足够先进来测试数据库。