bash 中的进程间通信在多个后台函数中读取命令

bash 中的进程间通信在多个后台函数中读取命令

我试图让以下代码从主输入中读取,然后在一个函数中读取该代码,然后能够将其发送到另一个函数的输入中,但我无法使其正常工作,并且需要将其输入到读取命令以便能够被解析

coproc test {
for i in $(seq 0 9)
    do
        sleep 1
        echo $i
done
}
input() { while read -u 3 gr
    do
        echo sent: $gr # this should send to output function
done
}
output() { while read idk
    do
        echo received: $idk | sed s/r/R/ | sed 's/5/five/' # this should receive from input function
done
}
exec 3>&${test[0]}
exec 4>&${test[1]}
input <&3 &>4 & # remove >&4 to see output
export input_PID=$!
output <&4 &
sleep 11
exec 3>&- 4>&-
echo finished

我已经尝试了 fd 的各种重定向,但似乎没有任何效果,请帮忙,这个想法是用户将能够(基于输出函数读取的内容)将命令发送到输入函数,而无需复制每个函数的代码,反之亦然(输入函数也可以发送到输出函数),发送到 fd3 或 fd4 不起作用,因为它似乎绕过读取本身并直接发送到接收最终输出的命令

请注意,这只是一个最小的示例,完整的用法在这里:

脚本的基本流程布局(每个缩进代表源深度或子流程深度):

Code_Bash
    . ./modules/module_controller
        . ./modules/module_trap
            . ./modules/module_finish
        until [[ $FIN == 1 ]] ; do
        . ./modules/module_loader
            . ./modules/module_colors
            . ./modules/module_tracker
            . ./modules/module_config
            . ./modules/module_kill_all_panes
            . ./modules/module_irc_session
                . ./modules/module_input
            . ./modules/module_irc_read
                . ./modules/module_output
                . ./modules/module_handler
                . ./modules/module_user_input
            . ./modules/module_array
            if [[ -z $IRC_NC_PID && $IRC_FIN == "0" ]] ; then
            . ./modules/module_coproc_nc
            . ./modules/module_rest_of_script
            fi
            . ./modules/module_null
        done

https://github.com/mgood7123/UPM/blob/master/Files/Code/modules/module_loader(这是连续执行的)

https://github.com/mgood7123/UPM/blob/master/Files/Code/modules/module_coproc_nc

https://github.com/mgood7123/UPM/blob/master/Files/Code/modules/module_irc_read(核心模块在单独的后台进程中运行)

https://github.com/mgood7123/UPM/blob/master/Files/Code/modules/module_irc_session(核心模块在单独的后台进程中运行)

https://github.com/mgood7123/UPM/blob/master/Files/Code/modules/module_rest_of_script(这运行 IRC_READ 和 IRC_SESSION 的后台函数)

答案1

问题是你混淆了输入和输出:

exec 3>&${test[0]}
exec 4>&${test[1]}
input <&3 &>4 &

您打开两者&3&4仅用于写入。但第一个只能读取。读取&3失败,因为您打开 fd 仅用于写入。你需要的是

exec 3<&${test[0]}

答案2

首先,什么在你的脚本中不起作用:

exec 3>&${test[0]}

作为 coproc 输出,${test[0]}是一个文件描述符,旨在读取而不是写入。假设你的意思是3<&${test[0]}

input <&3 &>4 &

首先,&>4意味着“将 stdout 和 stderr 重定向到名为 4 的文件”,您可能指的是>&4.现在,FD #4 是 coproc 的输入test(顺便说一句,测试不会读取它),因此重定向没有什么意义。

output <&4 &

如果没有拼写错误,FD #4 将是一个输出文件描述符(绑定到 coproc 的标准输入),您无法从中读取。


现在我将尝试为您提供一个工作代码,假设您想要:

  • 一个后台进程input从 FD #3 读取并将所有内容发送到,output并在每一行前面加上“已发送”。
  • 另一个后台进程output读取input发送的任何内容,在前面添加“已接收”,进行一些字符串处理并将结果写入标准输出

通常,这会像这样简单:

test() for i in {0..9}; do sleep 1; echo $i; done    # No coproc

input() while read gr; do echo sent: $gr; done       # Reads from stdin, not FD #3

# output() unmodified

exec 3> >(input | output)
test >&3

但我的印象是,无论出于何种原因,您都希望单独生成并放入input后台。然后试试这个:outputtest

exec 4> >(output)
output_PID=$!

exec 3> >(input >&4)
input_PID=$!
exec 4>&-

test >&3 &
wait

相关内容