繁体   English   中英

从文件描述符读取的循环(在后台进程中)不退出

[英]While loop (in a background process) reading from file descriptor does not exit

我将首先解释我的问题陈述。 我有一个command1,它在stderr和stdout上生成数据,stderr通过管道传输到command2,而stderr应该go到一个后台进程,该进程不断调用API。

相同的虚拟示例:

#!/bin/bash

set -e;

metric_background_process () {
    # This while loop waits till there is a line to read
    while read -u 3 -r line; do
        echo $line;
    done;
    
    # This never prints !!!
    echo "Done"
}

tmp_dir=$(mktemp -d)
mkfifo "$tmp_dir/f1"

# Allocate a file descriptor to the named pipe
# to allow read and write from it.
exec 3<> "$tmp_dir/f1"

metric_background_process <&3 &
pid=$!


# Main commands (stdout is being piped to stderr as a dummy case)
cat ./assets/random_file 1>&3

exec 3<&-

wait $pid

输入文件包含:1 到 9,其中 9 是最后一行。

观察到 Output:

1
2
3
4
5
6
7
8

shell 打印8后等待, 9不打印,程序不会自行停止。

无论我尝试什么, while循环都不会退出。 也许我错过了一些简单的东西,任何帮助或进一步的澄清问题将不胜感激。

父 shell 正在打开 fifo 以进行读/写 ( <> )。 子shell ( & ) 继承了 FD,因此它也打开了 fifo 以进行读/写。 当父级关闭 FD 时,子外壳仍在打开 fifo 进行写入,因此写入端永远不会关闭,因此读取端( read -u 3 )无法获得EOF

为了让它更简单一点——

剧本:

$ cat foo.sh 
metric_background_process () {
    local fifo=$1

    while read line; do
        echo $line
    done < $fifo
    
    echo "Done"
}

tmp_dir=$(mktemp -d)
fifo="$tmp_dir/f1"
mkfifo "$tmp_dir/f1"

metric_background_process $fifo &
pid=$!

exec 3> $fifo

for i in {1..5}; do
    echo i=$i >&3
done

exec 3>&-

wait $pid

结果:

$ bash foo.sh
i=1
i=2
i=3
i=4
i=5
Done

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM