Zol*_* K. 7 bash io-redirection function
请注意,我们从一个循环返回,该循环被重定向。
我不知道,我是否应该担心“文件”的写入缓冲区。
function f {
i=1
while :
do
echo aaaaaaaaaaaaabbbbbbbbbbbbbbbbb
((i++))
if [ $i -gt 3 ]
then
return # return while redirected
fi
done >> file # writing to file
}
f
Run Code Online (Sandbox Code Playgroud)
注意:我知道这个函数可以很容易地重写,所以它不会从重定向循环内返回。但是,这只是针对此问题的一个简化示例。
因此,请不要尝试改进此代码。
我对解决方法也不感兴趣。
我唯一的问题是,是否有我应该特别注意的事情。就像文件描述符没有正确关闭。或者有时我可以期望只有一半的缓冲区(即“aaaaaa”)被写入文件。
我想知道,如果这是一个非常糟糕的主意,为什么?或者它可能会在没有不可预见的竞争条件或类似条件的情况下工作?(但同样,我不想要像“这很糟糕,因为你应该使用这个和这个模式”这样的答案)
Sté*_*las 11
虽然每个命令都可能有自己的写缓冲区,但没有在命令之间共享的写缓冲区,即使是 bash 内置的(或者甚至是同一命令的两次调用,无论是否内置)。
即使 ksh93 已知会进行一些 I/O 优化(例如,它会预读并共享一些输入数据(导致一些错误)),也不会这样做。
因此,在这方面将是安全的。在一个命令完成后,就像你的echo aaaaaaaaaaaaabbbbbbbbbbbbbbbbb
, 并且如果它没有分叉在后台运行的无人值守进程,你可以保证所有的 I/O 都已经完成。
虽然有一些注意事项。在一个函数中:
f() {
{
echo x
return
echo y
} > file
echo something else
}
Run Code Online (Sandbox Code Playgroud)
在 Bourne shell(和仅 Bourne shell)中,这return
会破坏内部命令组的输出,但不会像在那个古老的 shell 中那样从函数返回,由于重定向,该命令组将在子 shell 中运行(所以你d 见something else
)。
这不再发生在像 的现代 shell 中bash
,但是如果您编写以下代码,您在 bash 中会遇到同样的问题:
f() {
(
echo x
return
echo y
) > file
echo something else
}
Run Code Online (Sandbox Code Playgroud)
或者
f() {
{
echo x
return
echo y
} | tr xy ab
echo something else
}
Run Code Online (Sandbox Code Playgroud)
请注意在某些情况下不等待某些命令。在:
f() {
{
echo >(sleep 1; echo x)
return
} > file
}
f; cat file
Run Code Online (Sandbox Code Playgroud)
您可能会发现x
它没有出现,因为它cat
是在echo x
.
一些外壳(虽然不是bash
)与管道组件有类似的潜在问题,而不是最右边的。