我一直在从事大学项目,其中有一些小的脚本,它们在简单的数据库上执行操作(例如选择信息),服务器脚本通过管道从客户端脚本的各种实例获取请求命名为server.pipe并通过单个客户端的命名管道返回其结果(通常是文本文件的几行)。
对于多行响应,我尝试在客户端中使用while循环以继续从管道中读取内容,我使用了类似的方法:
read response < $id.pipe
while [ $response != "end_result" ]; do
echo $response
read response < $id.pipe
这有时会返回完整的结果,有时会返回部分结果,而有时则不返回全部结果。当它没有返回完整结果时,我认为正在运行的脚本被管道阻塞,因为调试语句向我表明它没有执行其最后几行。
我用这个代替它
tail <$return_pipe &
我知道即使关闭了管道,尾部也会从管道中读取信息,但是我需要帮助解释导致第一个管道出现故障的情况,因为我现在正在编写有关分配的报告。我已经读了很多书,但我需要一些帮助。
如果有人想知道,服务器脚本正在像这样调用脚本:
return_pipe=${ar[4]}.pipe
./select.sh ${ar[1]} ${ar[2]} ${ar[3]} >$return_pipe &
选择脚本返回结果的部分是这个
echo "start_result"
cut -d' ' -f$3 ./$1/$2
echo "end_result"
如果有人能帮助我理解并解释这一点,我们将不胜感激。这是我的第一篇文章,所以我希望我也对它进行了适当的格式化!谢谢
答案 0 :(得分:0)
发生这种情况是因为fifo不是面向数据包的。这是一条小溪。
这意味着可能在内存中串联多个写入,并且在不读取所有管道缓冲区的情况下关闭管道会丢弃其余部分。 这是否会发生是一个种族条件。这是有效的事件顺序:
下面是一个带有睡眠的代码示例,以确保顺序良好:
rm fifo; mkfifo fifo
{
echo "hello" > fifo
sleep 1
echo "world" > fifo
} &
for i in 1 2
do
echo "Reading..."
{ read var; } < fifo
sleep 1
echo "Read: $var"
done
这将输出您期望的结果:
Reading...
Read: hello
Reading...
Read: world
这是失败的事件顺序:
需要一些睡眠才能做到这一点:
rm fifo; mkfifo fifo
{
echo "hello" > fifo
echo "world" > fifo
} &
for i in 1 2
do
echo "Reading..."
{ sleep 1; read var; } < fifo
echo "Read: $var"
done
现在它将打印:
Reading...
Read: hello
Reading...
并挂起,因为world
丢失了。
您应该改为从服务器的两个客户端打开一次fifo,并继续写入同一打开的FD。这样就可以确保流畅高效的通信,而不会丢失任何数据。