如果我们使用,echo 1234 >> some-file
那么文档会说明输出已被附加。
我的猜测是,如果 some-file 不存在,那么 O_CREAT 将创建一个新文件。如果>
使用,则 O_TRUNC 将截断现有文件。
如果发生以下情况>>
:文件是否会以 O_WRONLY (或 O_RDWR) 形式打开并试图结束并完成写入操作,模拟 O_APPEND ?或者文件是否会以 O_APPEND 形式打开,让内核确保附加操作发生?
我问这个问题是因为当输出文件来自 NFS 安装点时,conserver 进程会覆盖由 echo 插入的一些标记,并且 NFS 文档说服务器不支持 O_APPEND,因此客户端内核必须处理它。我猜 conserver 进程正在使用 O_APPEND ,但不确定>>
linux 上的 bash,因此在这里提出问题。
答案1
我跑了这个:strace -o spork.out bash -c "echo 1234 >> some-file"
来弄清楚你的问题。这是我发现的:
open("some-file", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3
我运行命令的目录中不存在名为“some-file”的文件echo
。
答案2
这不仅是在 Bash 中完成的,也是标准所要求的。
附加的输出重定向应导致名称由单词扩展产生的文件在指定的文件描述符上打开以进行输出。文件被打开,就像打开()POSIX.1-2008 系统接口卷中定义的函数是使用 O_APPEND 标志调用的。如果该文件不存在,则应创建该文件。
因此,任何符合 POSIX 标准的 shell 都必须这样做。在某些 Unix 系统上,/bin/sh
可能是非 POSIX Bourne shell(Bourne shell 最初是在O_APPEND
发明之前编写的),可用的 POSIX shell 通常是ksh
,它将sh
在不同的路径位置(例如 Solaris 的/usr/xpg4/bin
.
答案3
查看源代码,它确实使用了 O_APPEND。对于 bash 4.3.30,make_cmd.c
第 710-713 行:
case r_appending_to: /* >>foo */
case r_append_err_and_out: /* &>> filename */
temp->flags = O_APPEND | O_WRONLY | O_CREAT;
break;
答案4
让我们研究一下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
其他 shell,即busybox' 的dash
、dash
、和的行为方式相同。sh
mksh
该选项-e open
表示-e trace=open
仅跟踪open()
系统调用。