什么可能会导致符号链接路径的 openat 调用出现 EROFS 错误,但只是有时?

什么可能会导致符号链接路径的 openat 调用出现 EROFS 错误,但只是有时?

我正在尝试调试一个问题,该问题只是间歇性地出现,通常每台服务器只出现一两次,然后它就消失了。我有一个应用程序尝试使用标志打开锁定openat()文件O_WRONLY|O_CREAT。由于环境配置的原因,此锁定文件驻留在必须位于只读网络共享上的目录中。 (从技术上讲,这是一个 AWS EFS 共享,但它看起来就像是一个 NFS 共享)

因为挂载点是只读的,所以我们在应用程序期望锁定文件所在的路径放置了一个符号链接;符号链接目标是一个不存在的路径/tmp(可写)

# ls -l /mnt/share/files/.LOCK
lrwxrwxrwx 1 nfsnobody nfsnobody 16 Jan  1  1970 /mnt/share/files/.LOCK -> /tmp/application.LOCK
# ls -l /tmp/application.LOCK 
ls: cannot access /tmp/application.LOCK: No such file or directory

通常情况下,这工作得很好。该应用程序打开目标链接,创建文件(在 下/tmp),一切都很好。但有时,通常是第一次配置服务器并启动应用程序时,应用程序无法写入此文件。写入失败并出现EROFS(只读文件系统)错误。

我已经运行strace -s 1024 -y -e trace=%file -f并捕获了错误,以及随后的成功,它们之间没有明显的区别:

...
[pid 17654] openat(AT_FDCWD, "/mnt/share/files/.LOCK", O_WRONLY|O_CREAT, 0666) = -1 EROFS (Read-only file system)
...
[pid 17654] openat(AT_FDCWD, "/mnt/share/files/.LOCK", O_WRONLY|O_CREAT, 0666) = 112</tmp/application.LOCK>
...

在此测试之前,/tmp/application.LOCK不存在,之后/tmp/application.LOCK是一个包含文本的常规文件test\n

运行 echostrace显示几乎相同的系统调用,并且每次尝试都会成功:

# strace -s 1024 -y -e trace=%file -f bash -c "echo test > /mnt/share/files/.LOCK`
execve("/usr/bin/bash", ["bash", "-c", "echo test > /mnt/share/files/.LOCK"], 0x7ffc3a86df10 /* 22 vars */) = 0
...
access("/usr/bin/bash", R_OK)           = 0
openat(AT_FDCWD, "/mnt/share/files/.LOCK", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3</tmp/application.LOCK >

我怀疑可能相关的一件事是该应用程序是一个 systemd 服务,运行于ProtectSystem=full,PrivateTmp=yesPrivateDevices=yes...但这并没有改变,所以我不确定为什么有时访问会起作用,有时会失败。 (是的,我检查了 systemd 创建的私有临时目录,而不仅仅是,并且当调用成功时,将按预期/tmp创建文件)/tmp/systemd-private-blah/tmp/

当使用写入符号链接时,什么可能会导致EROFS(只读文件系统)错误,但只是偶尔/间歇性?openat()

答案1

我可以通过 at.ftpd 守护进程确认这件事发生在我身上。 systemd.service 设置为DynamicUser=yes只读并导致 FS。

看到这里,DynamicUser 隐含了几种模式: systemd 动态用户与用户

相关内容