gpt4 book ai didi

bash - bash 重定向中的意外行为

转载 作者:行者123 更新时间:2023-11-29 09:15:11 25 4
gpt4 key购买 nike

我在 bash 中使用重定向时发现了一个奇怪且完全出乎意料的行为,即使我设法解决了它,我也想知道为什么会发生。

如果我运行这个命令:{ echo wtf >/dev/stdout ; } >> wtf.txt N 次,我希望看到充满 N 个“wtf”的行。我在文件中找到的是一行。

我认为由于第一个命令是以截断模式打开/dev/stdout,所以该模式被第二个文件描述符(wtf.txt)继承,然后被完全删除,但我想知道是否你们中的一些人可能会更好地解释它,这是正确的行为还是错误。

需要说明的是,我使用的命令是不同的,但是使用 echo 示例更容易理解。原始命令是一个需要输出文件作为参数的命令,因为我想要 stdout 上的输出,所以我将 /dev/stdout 作为参数传递。可以使用命令 openssl rand -hex 4 -out/dev/stdout >> wtf.txt 验证相同的行为。

最后,我设法通过以下方式解决了将追加操作委托(delegate)给 tee 的问题:{ echo wtf >/dev/stdout } | tee -a wtf.txt >/dev/null

最佳答案

您可以使用 strace 检查发生了什么:

strace -o wtf-trace.txt -ff bash -c '{ (echo wtf) > /dev/stdout; } >> wtf.txt'

在我的例子中,这将生成两个文件,如 wtf-trace.txt.12889wtf-trace.txt.12890。发生的事情是,进程 1 >> wtf.txt:

open("wtf.txt", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3
dup2(3, 1) = 1
close(3) = 0
clone(child_stack=0, .................) = 12890
wait4(-1, [{WIFEXITED(s) .............) = 12890
exit_group(0) = ?

第一个进程打开或创建“wtf.txt”以附加并获取 FD 3。之后它用 FD 3 复制 FD 1 并关闭 FD 3。此时它 fork (克隆),等待它退出并自行退出。

第二个进程 { echo wtf >/dev/stdout } 通过 FD 1 (stdout) 继承了文件,它做了:

open("/dev/stdout", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
dup2(3, 1) = 1
close(3) = 0
fstat(1, {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
write(1, "wtf\n", 4) = 4
exit_group(0) = ?

如您所见,它打开 /dev/stdout(注意 O_TRUNC)并获取 FD 3,dup2 将 FD 3 获取到 FD 1,关闭 FD 3,检查FD 1 并获取大小为 0 的文件 st_size=0,写入并退出。

如果你这样做| cat >> 然后第二个进程将它的 FD 1 连接到管道,该管道不可搜索或可截断...

注意:我只显示了 strace 生成的文件的相关行。

关于bash - bash 重定向中的意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33563896/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com