请注意,我们从循环中返回,该循环已重定向。
我不知道我是否应该担心“文件”的写入缓冲区。
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
注意:我知道这个函数可以很容易地重写,因此它不会从重定向循环中返回。然而,这只是出于此问题目的的一个简化示例。
所以请不要试图改进这代码。
我对解决方法也不感兴趣。
我唯一的问题是,是否有什么我应该特别注意的?就像文件描述符没有正确关闭一样。或者有时我可以预期只有一半的缓冲区(即“aaaaaa”)被写入文件。
我想知道这是否是一个非常糟糕的主意,为什么?或者也许它可以在没有不可预见的竞争条件或类似条件的情况下工作? (但同样,我不想要像“这很糟糕,因为你应该使用这个和这个模式”这样的答案)
答案1
虽然每个命令可能有自己的写入缓冲区,但即使是 bash 中内置的命令(甚至同一命令的两次调用,无论内置与否),命令之间也没有共享的写入缓冲区。
即使 ksh93 已知会进行一些 I/O 优化(例如,它会预读并共享一些数据)输入(导致一些错误)),不这样做。
因此,在这方面它是安全的。命令完成后(例如您的echo aaaaaaaaaaaaabbbbbbbbbbbbbbbbb
),并且假设它不会分叉在后台运行的无人值守进程,则可以保证所有 I/O 均已完成。
不过有一些注意事项。在这样的函数中:
f() {
{
echo x
return
echo y
} > file
echo something else
}
在 Bourne shell(以及仅限 Bourne shell)中,这return
会破坏内部命令组的输出,但不会像在那个古老的 shell 中那样从函数返回,由于重定向,该命令组将在子 shell 中运行(所以你' d 参见something else
)。
在像 这样的现代 shell 中,这种情况不再发生bash
,但是如果您编写以下内容,那么在 bash 中也会遇到同样的问题:
f() {
(
echo x
return
echo y
) > file
echo something else
}
或者
f() {
{
echo x
return
echo y
} | tr xy ab
echo something else
}
请注意,有些情况下某些命令不会被等待。在:
f() {
{
echo >(sleep 1; echo x)
return
} > file
}
f; cat file
您可能会发现它x
没有显示,因为cat
它之前运行过echo x
。
某些 shell(尽管不是bash
)与管道组件(最右边的组件除外)存在类似的潜在问题。