这不是一个“如何追加而不覆盖”的问题。我不是在寻找组合两个命令的输出的文件。这只是我犯的一个错误,我想了解为什么系统会这样做
我使用一个命令(在远程 ssh 命令行上)需要很长时间才能完成并将数据(每隔几秒逐行)输出到 stdout,因此我将其重定向到一个文件:
command > file.out &
有时远程会话会断开连接,但命令会继续在后台运行。我不知道这一点,所以我再次运行相同的命令,在第一个完成之前:
command > file.out &
当两个进程完成后,我希望(在阅读此站点上的一些答案之后)有一个文件,其中两个命令的行都弄乱了,但输出文件仅包含两次执行之一的输出。
为什么该文件的两个输出没有交织在一起(正如评论中警告的那样)这里)?最终文件属于 2 个输出中的哪一个?
编辑:
删除了其中一个问题(为什么输出文件没有锁定写入?),如其解释这里
答案1
当您使用重定向打开文件进行写入时>
,该文件是被截断的,即完全清空。然而却是不是删除并重新创建。
如果一个命令首先截断文件,然后向其中写入一些内容,并且如果另一个命令随后执行相同操作,则第一个命令在文件中的位置将不会更改。这意味着您有两个命令在两个独立的位置写入同一个文件,一个可能会覆盖另一个的输出,取决于写入顺序和写入的数据量。
所以,是的,文件中的数据很可能是两个程序输出的交织在一起的混乱,但这将取决于写入文件的顺序,以及写入的数据量和截断的时间。文件。
以下是交织来自两个命令的数据的示例:
#!/bin/sh
( { echo hello; sleep 2; echo world; } | cat >file ) &
sleep 1
echo 123 >file &
wait
这是此脚本中发生的情况:
- 第一个命令打开文件进行写入并截断它。它会写入
hello\n
它。 - 一秒钟后,第二个命令截断文件并写入
123\n
。此时,第一个命令的文件指针仍然指向文件的某个偏移量。 - 第一个命令继续写入
world\n
文件。
结果是一个中间有一段 nul 字符的文件:
$ hexdump -C file
00000000 31 32 33 0a 00 00 77 6f 72 6c 64 0a |123...world.|
0000000c
nul(00
在上面的输出中)来自这样一个事实:第一个命令的文件指针没有被第二个命令的文件截断重置,因此创建了一个“洞”。第二个命令仅写入,123\n
但如果写入更多数据,则会覆盖 nul:
$ hexdump -C file
00000000 31 32 33 34 35 36 77 6f 72 6c 64 0a |123456world.|
0000000c
这里我已经创建了第二个命令echo 1234567890
,但1234567
文件中只留下了。这是因为world\n
在第二个命令完成写入后,第一个命令继续在其文件指针所在的位置写入。