我有一个脚本,它将命令的输出与之前运行的同一命令的输出进行比较,它有效最多的时间,但有时它不会按预期工作。
我已经能够在一条测试线上重现该问题。我知道我可以轻松地将其分解为比较两个单独的文件,问题就会消失,但我想了解这里实际发生的情况,以及是否有办法以我的方式实现我想要实现的目标我正在努力实现它。
下面是我的命令运行多次的输出,您可以看到它在其中一种情况下回显“test”,但大多数时候它按预期工作。
root@dev:~# comm -13 /tmp/test <(echo '"test"' | cut -d'"' -f2 | sort -u | tee /tmp/test)
root@dev:~# comm -13 /tmp/test <(echo '"test"' | cut -d'"' -f2 | sort -u | tee /tmp/test)
root@dev:~# comm -13 /tmp/test <(echo '"test"' | cut -d'"' -f2 | sort -u | tee /tmp/test)
root@dev:~# comm -13 /tmp/test <(echo '"test"' | cut -d'"' -f2 | sort -u | tee /tmp/test)
root@dev:~# comm -13 /tmp/test <(echo '"test"' | cut -d'"' -f2 | sort -u | tee /tmp/test)
test
root@dev:~# comm -13 /tmp/test <(echo '"test"' | cut -d'"' -f2 | sort -u | tee /tmp/test)
root@dev:~# comm -13 /tmp/test <(echo '"test"' | cut -d'"' -f2 | sort -u | tee /tmp/test)
root@dev:~# comm -13 /tmp/test <(echo '"test"' | cut -d'"' -f2 | sort -u | tee /tmp/test)
我正在跑步Ubuntu 10.04
,bash 4.1-2ubuntu3.5
并且coreutils 7.4-2ubuntu3
答案1
是的,这是一个竞争条件。
问题是 shell 同时启动管道中的所有进程,并且 tee 在启动时截断输出文件。如果 tee 比 comm 快,则该文件对于 comm 来说是空的,否则不是。
如果运行多次(可能在循环中),可以看到管道行为:
date '+first: %T'|(cat>&2;sleep 5)|date '+second: %T'
答案2
你的台词让我有点困惑,因为不清楚两次出现的“测试”应该是什么。 - 因此我真的理解你的 shell 也很混乱。 ;)
如果我理解正确,第一个“/tmp/test”应该与命令的旧输出相对应,第二个与新输出相对应。
您可以确定 stdin 将包含新输出,但文件的内容未定义:在comm
读取该文件时,tee
可能尚未启动。在这种情况下,它仍将包含上次运行的旧“测试”行。或者tee
可能已经完成了。在这种情况下,它将包含当前运行的“测试”行。或者tee
刚刚开始,已经清除了文件,正要写入新的内容。如果发生这种情况,您将比较来自标准输入的“测试”与空文件,然后您将看到输出。
您想要比较两个不同的输出。如果没有两个不同的文件,我看不出有什么方法可以做到这一点。拥有两个不同的(正确命名的)文件也使该行更具可读性,并解决了开始时的混乱。 ;)