在_程序替換_的上下文中理解 i/o 重定向
執行 GNU bash,版本 4.3.11(1)-release (x86_64-pc-linux-gnu)。
從有興趣了解 i/o 處理和相關速度問題的使用者的角度來看,我並不真正理解程序替換(ProcSub)。我使用 ProcSub 編寫腳本,所以我對文件描述符 0、1、2 有一些了解,但僅此而已。我讀過一些相當不錯的文章,例如$$ 1 $$, 和雜項。維基,例如$$ 2 $$,$$ 3 $$,後者聲明:“程序替換將一個程序(或多個程序)的輸出(FD 1 和/或 2)饋送到另一個程序的標準輸入(FD 0)”。通過最簡單的定義並且僅針對一個程序,它在操作上似乎與簡單的未命名管道沒有什麼不同。
tee
從 i/o 的角度來看,我從 .開始研究它本身就很有趣。tee
允許將*“標準輸入到標準輸出以及作為參數給出的任何文件”*。所以 :$ for i in 1 2 3; do (( j=i+10 )); printf "%d\n" $j > file_$i; done # so each file in file_{1,2,3} contains the numeral in its name + 10. $ cat file_{1,2,3} | tee file_4 11 12 13 $ cat file_4 11 12 13
顯然,我對看到填充我的螢幕 ala Matrix 的數據不感興趣,所以當:
***1)***我添加了一個管道和
shasum
‘輸出的重定向……$ cat file_{1,2,3} | tee file_4 | shasum -a 256 > file_4.sha256 $
上面的一個班輪安靜地退出,file_4 和以前一樣(上圖),file_4.sha256 包含計算的 SHA256 總和。
上面只是一個例子來說明我的問題,試圖理解中間 i/o。我的外行的結論是,
tee
將cat
cmd 的輸出保存在 file_4 中,並且通常發送到 stdout 的副本實際上並未發送到 stdout 而是通過管道傳輸到shasum
.**問:**這甚至是遙不可及的嗎?
***2)***我嘗試與 ProcSub 相同:
$ cat file_{1,2,3} | tee file_4 >(shasum -a 256 > file_4.sha256) 11 12 13 $
-> 沒有任何發送到 FD 1 的 stdout 重定向
tee
?**問:**我不清楚 ProcSub 對 i/o 做什麼或不做什麼(顯然在這種情況下它不影響 i/o),可以使用其機制的解釋。
***3)***我嘗試使用 ProcSub 並將最終標準輸出重定向到 file_4:
$ cat file_{1,2,3} | tee >(shasum -a 256 > file_4.sha256) > file_4 $
這一次,單線再次安靜地存在。
**問:**所以一般問題是:對於上述 3 種情況(或至少對於第二種和第三種情況),如何處理 i/o?i/o 術語有明顯和可見的差異(僅查看最終標準輸出),但有時不同的 i/o 過程會導致顯示的最終結果相同。德克薩斯州。
成語
>(...)
只是意味著(用外行術語):“文件名”。它作為“文件名”工作(有點,一切都會在瞬間變得清晰):
$ echo <(date) /proc/self/fd/11
或您的作業系統上的其他號碼/名稱。但是 echo 確實列印了一個名稱,就像您這樣做一樣:
$ echo ProcSubs11 ProcSubs11
如果存在帶有標籤 ProcSubs11 的文件,您還可以執行以下操作:
$ cat ProcSubs11 contents_of_file_ProcSubs11
你可以做同樣的事情:
$ cat <(date) Fri Jan 15 21:25:18 UTC 2016
不同之處在於“流程替換”的實際名稱是“不可見的”,並且詳細資訊比讀取簡單文件要長得多,正如如何實現流程替換的連結中的所有痛苦細節中所描述的那樣在重擊中?.
說了這麼多,讓我們回顧一下你的項目。
問1
…在操作上似乎與簡單的未命名管道沒有什麼不同…
好吧,“流程替換”完全基於
unnamed pipe
您給定的第一個連結狀態:
- bash 程序為稍後創建的兩個程序之間的通信創建了一個未命名的管道。
不同之處在於連結中解釋的所有〜6個步驟都簡化為一個
>(...)
用於寫入和讀取的<(...)
習語。而且,可以說連接(管道)有一個名稱,就像一個文件一樣。只是該名稱對使用者隱藏(
/proc/self/fd/11
如開頭所示)。範例 1
1)我添加了一個管道和shasum輸出的重定向……
$ cat file_{1,2,3} | tee file_4 | shasum -a 256 > file_4.sha256
那裡沒有“程序替換”,但值得注意的是(稍後)
tee
將接收到的內容髮送(寫入)stdin
到文件中file_4
**,**並將相同的stdin
內容髮送到stdout
. 它恰好連接到寫入 shasum 的管道(在這種情況下)。所以,簡而言之,用外行的話來說, tee 複製
stdin
到file_4
和shasum
。範例 2
2)我嘗試與 ProcSub 相同:
$ cat file_{1,2,3} | tee file_4 >(shasum -a 256 > file_4.sha256)
重新使用上面的描述(外行術語)來描述這個例子:
Tee 複製
stdin
到三個元素file_4
:shasum
和stdout
。為什麼?。記住這
>(...)
是一個文件的名稱,讓我們把它放在行中:$ cat file_{1,2,3} | tee file_4 /proc/self/fd/11
tee 正在為兩個文件
file_4
和shasum
(通過“Process Substitution”)提供輸入,並且stdout
oftee
仍然連接到其預設位置:控制台。這就是您在控制台中看到數字的原因。為了使這個例子完全等於1),我們可以這樣做:
$ cat file_{1,2,3} | tee file_4 > /proc/self/fd/11 ### note the added `>`
變成(是的,必須使用
>
和 之間的空間。>(
$ cat file_{1,2,3} | tee file_4 > >(shasum -a 256 > file_4.sha256)
那就是將
tee
’s stdout 重定向到“Process Substitution”。問題 3
問:所以一般的問題是:如何處理上述 3 種情況的 i/o
我相信我只是解釋了這 3 個案例,如果不清楚,請發表評論。
Q 4(在評論中,請編輯並添加問題)
為什麼 <(…) 構造在第三種情況下不起作用。
因為(用外行的話)你不能將公插腳插入公插座。
<(…) 習語從“程序替換”中讀取內容,因此提供“輸出”,應插入
stdin
到外部命令中。外部命令tee
正在嘗試連接stdout
(喜歡)元素。所以,那一對是無法匹配的。重要說明: 該命令
cat
在應用於“程序替換”時隱藏了一些細節,因為這兩個命令將給出相同的輸出:$ cat <(date) $ cat < <(date)
一切都是正確的,但從誤導性的平等得出結論是錯誤的。