需要腳本將 STDIN 和 STDOUT 重定向到命名管道
我有一個啟動身份驗證助手(我的腳本)並使用 STDIN/STDOUT 進行通信的應用程序。
我想將此腳本中的 STDIN 和 STDOUT 重定向到兩個命名管道,以便與另一個程序進行互動。
例如:
腳本標準輸入 > 管道
1 腳本標準輸出 < 管道 2
這是我要完成的流程:
$$ Application $$-> 啟動輔助腳本,寫入輔助 STDIN,從輔助 STDOUT 讀取(例如:STDIN:username,password; STDOUT:LOGIN_OK)
$$ Helper Script $$-> 讀取 STDIN(來自應用程序的數據),轉發到 PIPE1;從 PIPE2 讀取,將其寫回 STDOUT 上的應用程序
$$ Other Process $$-> 從 PIPE1 輸入讀取,處理並將結果返回給 PIPE2
cat 命令幾乎可以為所欲為。如果有將 STDIN 複製到 STDERR 的選項,我可以讓 cat 使用命令執行此操作(假設虛構選項 -e 回顯到 STDERR 而不是 STDOUT):
cat -e PIPE2 2>PIPE1(從 PIPE2 讀取並將其寫入 STDOUT,複製輸入,通常會從 STDERR 到 PIPE1)
正如我後來發現的那樣,我之前的答案並不是一個理想的解決方案。它有三個缺點:一個在標準輸入關閉時它沒有關閉(標準輸入上的 eof)。其次, cat (以及 tee 等其他實用程序)在關閉它正在寫入的管道的讀取端時具有一些奇怪的特徵(如果您關閉並重新打開該腳本正在寫入的管道的讀取端它將開始緩衝所有數據,並且僅在此過程停止時才刷新它,這對我來說顯然是一個顯示停止器)。第三,這種情況下的後台程序可以是孤立的。
在處理完這些問題之後,我的新腳本解決了上述所有三個問題。希望它對某人有好處。
#!/bin/ksh # # USAGE # helper <path_to_CLIENT_TO_SERVER_pipe> <path_to_SERVER_TO_CLIENT_pipe> # CS=$1 SC=$2 exec 3>&0 trap 'exit;' CHLD { while read LINE; do #STDIN -> CS print $LINE >>$CS; done; } <&3 & while true; do #SC -> STDOUT read IN <$SC; retCode=$? if [[ $retCode -eq 0 ]]; then print $IN; else sleep 1; fi done
在這種情況下,我們只有一個後台程序,即讀取標準輸入的一個。如果標準輸入關閉,它將退出,我們擷取它並退出前台腳本。前台腳本永遠不需要退出,因為它正在從管道讀取,無論該管道另一端發生什麼,它都應該始終執行此操作。使用讀取雖然效率較低,但在讀取/寫入給定管道的外部程序啟動或關閉時不會遇到緩衝問題。此腳本僅在標準輸入關閉時存在。
這是一個最終可以滿足我要求的腳本。它讀取 STDIN 並將其輸出到 PIPE1,並從 PIPE2 獲取並將其輸出到 STDOUT。
#!/bin/ksh exec 3>../pipes/PIPE1 exec 4<../pipes/PIPE2 { cat; } <&4 >&1 & { cat; } <&0 >&3 wait
這樣做的目的是將幫助應用程序的輸入/輸出重定向到可以由 3rd 方應用程序處理的兩個管道(這是典型的身份驗證幫助程序)。