我应该使用单尖括号还是双尖括号来重定向到 /dev/null?

我应该使用单尖括号还是双尖括号来重定向到 /dev/null?

大多数答案在这里[1] [2] [3]使用单个尖括号重定向到 /dev/null,如下所示:

command > /dev/null

但附加到 /dev/null 也可以:

command >> /dev/null

除了额外的字符之外,还有什么理由不这样做呢?这些中的任何一个对于 /dev/null 的底层实现来说“更好”吗?

编辑:
打开(2)联机帮助页查找在每次以追加模式写入文件之前调用:

O_APPEND
文件以附加模式打开。在每次 write(2) 之前,文件偏移量位于文件末尾,就像 lseek(2) 一样。文件偏移量的修改和写入操作作为单个原子步骤执行。

这让我认为使用可能会带来微小的性能损失>>。但另一方面,根据该文档,截断 /dev/null 似乎是一个未定义的操作:

O_TRUNC
如果文件已经存在并且是常规文件并且访问模式允许写入(即,是 O_RDWR 或 O_WRONLY),则它将被截断为长度 0。如果文件是 FIFO 或终端设备文件,则忽略 O_TRUNC 标志。否则,O_TRUNC 的效果未指定。

POSIX 规范说>应截断现有文件, 但O_TRUNC 是为设备文件实现定义的没有说明 /dev/null 应如何响应被截断

那么,截断 /dev/null 实际上是未指定的吗?并做查找调用对写性能有什么影响?

答案1

根据定义,/dev/null会下沉写入其中的任何内容,所以不管你是否以append模式写,都被丢弃了。由于它不存储数据,因此实际上没有任何可附加的内容。

所以最后,只是> /dev/null用一个>符号写得更短而已。

至于编辑后的补充:

open(2) 联机帮助页显示,每次以追加模式写入文件之前都会调用 lseek。

如果你仔细阅读,你会看到它说(强调我的):

文件偏移量位于文件末尾,仿佛与查找(2)

意思是,它并不(需要)实际调用lseek系统调用,并且效果也不严格相同:不进行调用lseek(fd, SEEK_END, 0); write(fd, buf, size);O_APPEND追加模式下的写入不同,因为通过单独的调用,另一个进程可以写入文件在系统调用之间,丢弃附加的数据。在追加模式下,这种情况不会发生(除非超过NFS,不支持真正的追加模式)。

标准中的文字此时没有提及lseek,仅写入应位于文件末尾。

那么,截断 /dev/null 实际上是未指定的吗?

从您引用的经文来看,显然它是实现定义的。这意味着任何理智的实现都将与管道和 TTY 执行相同的操作,即什么也不做。疯狂的实现可能会做其他事情,并且对于其他设备文件来说,截断可能意味着一些明智的事情。

lseek 调用对写入性能有影响吗?

测试一下。这是在给定系统上确定的唯一方法。或者阅读源代码以查看追加模式在哪里改变了行为(如果有的话)。

答案2

如果您想要效率,请command >&-改为使用。这会关闭文件描述符而不是重定向它,因此根本不会浪费时间向其写入内容。

相关内容