多個程序之間的通信
我有一個 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
我在哪裡輸入
hello
和world
.