Linux 中的 coproc 命令与示例
Linux 中的 coproc 命令是一个 shell 命令,它允许我们创建一个通过两个管道连接到调用 shell 的协同进程。其中一个管道使我们能够发送输入,而另一个管道使我们能够读取输出而不必求助于命名管道。协同进程在子外壳中异步执行。此命令可以在 bash 4.0 以上版本使用。
句法:
coproc command args #first command
coproc name command args #second command
第一个命令用于简单命令的情况。不得为命令提供名称,因为在简单命令的情况下,它被解释为简单命令的第一个字。在复合命令的情况下,使用第二个命令。如果未提供名称,则默认情况下 COPROC 是“名称”。执行协进程时,会在执行 shell 的上下文中创建一个名为“name”的数组(如果命令中未提供名称,则默认为 COPROC)。该数组的第一个元素是输出描述符,而数组的第二个元素是协同进程的输入描述符。在执行 shell 和协同进程之间建立了一个双向管道。 Bash 将这些管道的文件描述符放入数组中:
- name[0] 是管道的文件描述符,该管道连接到执行 shell 中协同进程的标准输出。
- name[1] 是管道的文件描述符,该管道连接到正在执行的 shell 中协同进程的标准输入。
这些管道是在命令完成任何重定向之前建立的。这些文件描述符可以用作 shell 命令和使用标准字扩展的重定向的参数。变量 name_PID 存储进程 ID 号。 wait内置命令可用于等待协同进程完成其执行。 coproc 命令总是返回成功,因为它是作为异步命令创建的。协程的返回状态与命令的退出状态相同。
使用 coproc 命令
1.从下面提到的示例代码中可以看出, coproc 命令中没有给出名称,因此默认情况下 COPROC 是数组的名称。 COPROC[@] 打印数组的元素,该数组存储分别连接到输出和输入的文件描述符。 COPROC_PID 存储进程 ID 号。 COPROC[0] 使我们能够读取协进程的输出
coproc (echo $(whoami))
echo "The coprocess array is ${COPROC[@]}"
echo "The PID of the coprocess is ${COPROC_PID}"
read -r o <&"${COPROC[0]}"
echo "The user is $o which is the output of the coprocess"
2.下面提到的代码打印 geeksforgeeks 作为输出。 bash 的输入是使用 gfg[1] 给出的,gfg[1] 是连接到输入的管道的文件描述符。
coproc gfg { bash ; }
echo 'echo geeksforgeeks' >&"${gfg[1]}"
read output <&"${gfg[0]}"
echo $output
3.协同进程的文件描述符只能被生成协同进程的进程访问。它们不会被子外壳继承(例如:在括号内启动的任何命令都在新的子外壳中启动)。从下面提到的代码可以看出,错误显示在第二种情况下,因为括号内的命令是在新的 shell 中启动的,并且协同进程的文件描述符只能由生成它的进程访问。
coproc gfg ( read -r input; echo "${input}" )
echo "PID:${gfg_PID}"
#first case
echo "geeksforgeeks" >&"${gfg[1]}"
read -r output1 <&"${gfg[0]}"
echo "The output of coprocess is ${output1}"
#second case
(echo "geeksforgeeks" >&"${gfg[1]}") #This will cause an error
read -r output2 <&"${gfg[0]}"
echo "The output of coprocess is ${output2}"
4.下面提到的代码中的 tr 命令会将输入中字母“a”的所有实例替换为字母 b。文件描述符由 exec 语句关闭。请注意,在 4.3 以上的 bash 版本中允许以这种方式关闭。对于 4.3 之前的版本,您需要先将文件描述符存储在一个变量中,然后使用 exec 命令。
coproc gfg { tr a b; }
echo abbaaabbb >&"${gfg[1]}"
exec {gfg[1]}>&-
cat <&"${gfg[0]}"
coproc 命令优于 &运算符的优势
在后台运行协同进程也可以通过使用 &运算符来实现,该运算符可以简单地附加到命令中。诸如fg 、 kill和[jobspec]% 之类的命令可用于将进程带到前台或向其发送信号。但这不允许我们向后台命令发送输入或读取该命令的输出。这可以使用 coproc 命令来实现,该命令可以解释为具有与 &运算符相同的函数,并在执行 shell 和协同进程之间建立了双向管道。