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