Bash

多個程序之間的通信

  • April 14, 2017

我有一個 bash 腳本,它將 manager() 函式作為一個單獨的程序執行 x 次。如何從腳本中將消息轉發到所有 manager() 程序?

我已經閱讀了有關匿名管道的資訊,但我不知道如何與它共享消息。我嘗試使用命名管道進行操作,但似乎我必須為每個程序創建一個單獨的命名管道?

最優雅的方法是什麼?

到目前為止,這是我的程式碼:

#!/bin/bash

manager () {
   while :
   do
       echo "read what has been passed to \$line"
   done
}

x=1
while [ $x -le 5 ]
do
 manager x &
 x=$(( $x + 1 ))
done


while :
do
while read line
do
 echo "What has been passed through the pipe is ${line}"
 # should pass $line to every manager process

done < $1
done

exit 0

您要完成的任務的術語是多路復用

這可以在 bash 中相當容易地完成,但它確實需要一些更高級的 bash 功能。

我根據您創建了一個腳本,我認為它可以完成您想要完成的任務。我會在下面解釋。

#!/bin/bash
manager() {
 while IFS= read -r line; do
   echo "manager[$1:$BASHPID]: $line"
 done
}

fds=()
for (( i=0; i<5; i++ )); do
 exec {fd}> >(manager $i)
 fds+=( $fd )
done

while IFS= read -r line; do
 echo "master: $line"
 for fd in "${fds[@]}"; do
   printf -- '%s\n' "$line" >&$fd
 done
done

manager是一個 bash 函式,它簡單地從 STDIN 讀取並將其標識符和行寫入 STDOUT。我們使用$BASHPID而不是$$as$$不會更新子外殼(這是我們將用於啟動manager.

fds``manager是一個數組,它將保存指向各種衍生的 STDIN 管道的文件描述符。

然後我們循環並創建 5 個管理器程序。我使用for (( ))語法而不是您的方式,因為它更乾淨。這是特定於 bash 的,但該腳本所做的一些事情是特定於 bash 的,所以不妨一直走下去。

 

接下來我們到exec {fd}> >(manager $i). 這會做更多 bash 特定的事情。

其中第一個是{fd}>。這將抓取編號 10 或之後的下一個可用文件描述符,打開一個管道,將管道的寫入端分配給該文件描述符,並將文件描述符編號分​​配給變數$fd

>(manager $i)啟動manager $i並基本上替換>(manager $i)為該過程的 STDIN 路徑。因此,如果manager作為 PID 1234 啟動,>(manager $i)可能會被替換為/proc/1234/fd/0(這取決於作業系統)。

因此,假設下一個可用的文件描述符編號是 10,並且使用 PID 1234 啟動管理器,命令exec {fd}> >(manager $i)基本上變為exec 10>/proc/1234/fd/0,並且 bash 現在具有指向該管理器的 STDIN 的文件描述符。

然後由於 bash 將該文件描述符編號放入 中$fd,我們將該描述符添加到數組fds中以供以後使用。

 

其餘的很簡單。主機從 STDIN 讀取一行,遍歷 中的所有文件描述符$fds,並將該行發送到該文件描述符 ( printf ... >&$fd)。

 

結果如下所示:

$ /tmp/test.sh
hello
master: hello
manager[0:8876]: hello
manager[1:8877]: hello
manager[4:8880]: hello
manager[2:8878]: hello
manager[3:8879]: hello
world
master: world
manager[0:8876]: world
manager[1:8877]: world
manager[3:8879]: world
manager[2:8878]: world
manager[4:8880]: world

我在哪裡輸入helloworld.

引用自:https://unix.stackexchange.com/questions/132102