Shell
請幫助解釋這個 bash 輸出重定向
該腳本作為對Question的回答發布。我正在努力弄清楚發生了什麼。
result=$( { { ssh host app-status >&3 3>&-; echo "$?" } | { until read -t1 ret; do printf . >&2 done exit "$ret" } } 3>&1 )
這是我的解釋,但我確定這是錯誤的。
- 外部
{...} 3>&1
: fd 3 作為標準輸出的副本打開- 然後是管道的後半部分,’| { }` 無重定向
- 在讀取循環中,printf 的 stdout 與 stderr 重複,因此在 2.(上圖)中,所有輸出實際上都來自 stderr。
- 現在管道的前半部分
{ ssh ... } |
: ssh 的標準輸出被複製到 fd3 上(實際上是來自 1 的標準輸出。fd 3 被關閉,3>&-
因此標準輸出重新打開到原來的位置,並通過管道傳輸到 2。- 最後,
echo
只列印到標準輸出所以我的問題(理解問題)是;這與 printf 到 stderr 的結果相同嗎?voodo重定向到 3 實際實現了什麼?這裡有什麼非同步的嗎?
在內部
$(...)
,stdout (fd 1) 是一個管道。在管道的另一端,shell 讀取輸出並將其儲存到$result
變數中。與:
$({ blah; } 3>&1)
我們使 fd 3 和 1 都指向blah
.
blah
是cmd1 | cmd2
。cmd1
與fd 1 指向另一個管道(指向 的管道)同時cmd2
啟動,但是我們不希望輸出進入該管道,我們希望它進入第一個管道,以便它可以儲存在.cmd1``cmd2``ssh``$result
所以我們有
{ ssh >&3; echo "$?"; } | cmd2
,所以只有echo
輸出到管道cmd2
。ssh
輸出 (fd 1) 轉到$result
.ssh
不需要 fd 3,我們在使用它設置 fd 1 (3>&-
) 後將其關閉。
cmd2
的輸入 (fd 0) 是第二個管道。在終止並在那裡輸出退出狀態之前,沒有任何東西寫入該管道(因為ssh
正在寫入第一個管道) 。ssh``echo
所以在
cmd2
(作為until
循環)中,read -t1
實際上是在等待超時直到ssh
退出。之後,會以fed byread
的內容成功返回。$?``echo