带有cat和tee的文件之前的奇怪行为

Dan*_*kov 3 unix linux bash shell

解决这个问题的方法是从一个衬套到一个衬套?是:

cat header main | tee main > /dev/null
Run Code Online (Sandbox Code Playgroud)

正如一些评论所注意到的,这不适用于大文件。

这是一个可行的示例:

$ echo '1' > h
$ echo '2' > t
$ cat h t | tee t > /dev/null
$ cat t
1
2
Run Code Online (Sandbox Code Playgroud)

并在哪里中断:

$ head -1000 /dev/urandom > h
$ head -1000 /dev/urandom > t
$ cat h t | tee t > /dev/null
^C
Run Code Online (Sandbox Code Playgroud)

该命令挂起,并在杀死它后留下:

$ wc -l t
7470174 t
Run Code Online (Sandbox Code Playgroud)

是什么导致命令卡住并无限增加行的上述行为?1行文件方案有什么不同?

Wil*_*ell 5

该行为是完全不确定的。当您这样做时cat header main | tee main > /dev/null,会发生以下情况:

1) cat opens header
2) cat opens main
3) cat reads header and writes its content to stdout
4) cat reads main and writes its content to stdout
5) tee opens main for writing, truncating it
6) tee reads stdin and writes the data read into main
Run Code Online (Sandbox Code Playgroud)

上面的顺序是一种可能的顺序,但是这些事件可能以许多不同的顺序发生。5必须在6之前,2必须在4之前,并且1必须在3之前,但是顺序完全可以是5,1、3、2、4、6。无论如何,如果文件很大,则很可能在完成步骤4之前执行步骤5,这将导致部分数据被丢弃。完全有可能首先发生步骤5,在这种情况下,先前main中的所有数据都将丢失。

您所看到的特殊情况很可能是猫在写操作时阻塞并在完成读取输入之前进入睡眠状态的结果。 tee然后将更多数据写入t管道并尝试从管道读取,然后进入睡眠状态,直到cat写入更多数据。 cat写入缓冲区,tee将其放入t,然后重复该循环,然后cat重新读取tee写入的数据t