Kam*_*ski 81 bash redirection sh
考虑像 Bash 或 sh 这样的 shell。在目标文件存在的情况下,>
和之间的基本区别>>
表现出来:
>
将文件截断为零大小,然后写入;>>
不截断,它写入(附加)到文件的末尾。如果文件不存在,则以零大小创建;然后写到。这对两个运营商都是如此。当目标文件尚不存在时,运算符似乎是等效的。
他们真的吗?
Kam*_*ski 109
号>>
本质上是“始终寻求文件结尾”,同时>
维护指向最后写入位置的指针。
(注意:我所有的测试都是在 Debian GNU/Linux 9 上完成的)。
不,它们不是等价的。还有一个区别。无论目标文件之前是否存在,它都可能表现出来。
要观察它,请运行一个生成数据并使用>
或>>
(例如pv -L 10k /dev/urandom > blob
)重定向到文件的进程。让它运行并更改文件的大小(例如使用truncate
)。你会看到它>
保持它的(增长的)偏移量,同时>>
总是附加到最后。
>
不会在意,它会在其所需的偏移量处写入,就好像什么也没发生一样;在截断偏移量超出文件末尾之后,这将导致文件恢复其旧大小并进一步增长,丢失的数据将用零填充(如果可能,以稀疏的方式);>>
将附加到新的末尾,文件将从其截断的大小开始增长。>
不会在意,它会在其所需的偏移量处写入,就好像什么也没发生一样;刚改变大小后,offset就在文件内部的某个地方,这会导致文件停止增长一段时间,直到offset到达新的末尾,然后文件才会正常增长;>>
将附加到新的末尾,文件将从其放大的大小开始增长。另一个例子是>>
在数据生成过程运行并写入文件时附加(使用单独的)一些额外的东西。这类似于放大文件。
>
将以其所需的偏移量写入并最终覆盖额外的数据。>>
将跳过新数据并将其追加(可能会发生竞争条件,两个流可能会交错,仍然不应该覆盖任何数据)。在实践中重要吗?有这个问题:
我正在运行一个在标准输出上产生大量输出的进程。将其全部发送到文件 [...] 我可以使用某种日志轮换程序吗?
这个答案说解决方案是logrotate
使用这样的copytruncate
选项:
创建副本后原地截断原始日志文件,而不是移动旧日志文件并可选择创建新日志文件。
根据我上面写的内容,重定向 with>
会立即使截断的日志变大。稀疏将节省一天,不应浪费大量磁盘空间。然而,每个连续的日志都会有越来越多的前导零,这些零是完全不必要的。
但是如果logrotate
在不保留稀疏性的情况下创建副本,则每次创建副本时,这些前导零将需要越来越多的磁盘空间。我还没有研究过工具行为,它可能足够智能,可以即时进行稀疏或压缩(如果启用了压缩)。尽管如此,零可能只会造成麻烦或充其量是中性的;他们没有什么好处。
在这种情况下,使用>>
而不是>
明显更好,即使目标文件即将被创建。
正如我们所看到的,这两个操作符不仅在开始时而且在以后的行为都不同。这可能会导致一些(微妙的?)性能差异。目前我没有有意义的测试结果来支持或反驳它,但我认为你不应该自动假设它们的性能总体上是相同的。