在 linux 上使用“>>”时,bash 是否会打开 O_APPEND 中的文件?

Pre*_*rem 38 linux nfs glibc files

如果我们使用,echo 1234 >> some-file则文档说明输出已附加。

我的猜测是,如果 some-file 不存在,那么 O_CREAT 将创建一个新文件。如果>使用,则 O_TRUNC 将截断现有文件。

的情况下 >>:文件是否会被打开为 O_WRONLY(或 O_RDWR)并寻求结束并完成写入操作,模拟 O_APPEND?还是将文件作为 O_APPEND 打开,将其留给内核以确保发生附加?

我问这个是因为当输出文件来自 NFS 挂载点时,保存进程正在覆盖由 echo 插入的一些标记,并且 NFS 文档说服务器不支持 O_APPEND,因此客户端内核将不得不处理它。我猜保护进程正在使用 O_APPEND ,但不确定 bash>>在 linux 上,因此在这里提出问题。

Bru*_*ger 61

我跑了这个:strace -o spork.out bash -c "echo 1234 >> some-file"找出你的问题。这是我发现的:

open("some-file", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3
Run Code Online (Sandbox Code Playgroud)

在我运行echo命令的目录中不存在名为“some-file”的文件。


Ran*_*832 51

这不仅在 Bash 中完成,而且是标准要求的。

来自单一 Unix 规范

附加的输出重定向将导致名称由单词扩展产生的文件被打开以在指定的文件描述符上输出。该文件被打开,就像在POSIX.1-2008 的系统接口卷中定义的open()函数是用 O_APPEND 标志调用的一样。如果该文件不存在,则应创建该文件。

因此,任何符合 POSIX 的 shell 都必须这样做。在某些 Unix 系统上,/bin/sh可能是非 POSIX Bourne shell(Bourne shell 最初是在O_APPEND发明之前编写的),可用的 POSIX shell 通常是ksh,它将sh在不同的路径位置(例如 Solaris 的/usr/xpg4/bin.

  • 有趣的是,一种没有这样做的 shell 是 Bourne shell。Bourne shell 在没有 O_TRUNC 和 lseek() 的情况下打开。那是因为它是在 O_APPEND 标志被添加到 `open()` 之前编写的。`>>` 本身是由其前身 Thomson shell 引入的。 (2认同)

Eri*_*ouf 32

查看源代码,它确实使用了 O_APPEND。对于第 710-713make_cmd.c行中的bash 4.3.30,请阅读:

case r_appending_to:                /* >>foo */
case r_append_err_and_out:          /* &>> filename */
  temp->flags = O_APPEND | O_WRONLY | O_CREAT;
  break;
Run Code Online (Sandbox Code Playgroud)


Fra*_*iat 19

让我们研究一下strace在本地(非 NFS)文件系统上使用:

$ strace -eopen -- bash -c "echo foo >> /tmp/testfile000" 2>&1 | grep /tmp/testfile000
open("/tmp/testfile000", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3

$ strace -eopen -- bash -c "echo foo > /tmp/testfile000" 2>&1 | grep /tmp/testfile000
open("/tmp/testfile000", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
Run Code Online (Sandbox Code Playgroud)

其他炮弹,即dashdashshbusybox的”和mksh行为方式相同。

该选项-e open表示-e trace=open仅跟踪open()系统调用。