理解“流程替代”的概念
我尋求一個針對一般受眾/非專業系統管理員的術語“流程替換”的簡單解釋,他們偶爾為個人項目進行伺服器環境維護,而不是每天為客戶或公司進行維護,如果可以在這裡提出要求的話。
- 發明這個概念是為了解決什麼問題
- 什麼過程被替換了,用什麼(名稱可能會誤導)?
- 它是否也被命名為“保留標準輸入”,如果是,為什麼?如果標準輸入設備擁有可以通過管道傳輸到另一個命令的標準輸入,那麼還有什麼可以“保留”比這更進一步的呢?
這可能有助於我理解以下命令:
bash <(wget -O - URL)
新手注意:
-O -
告訴wget
將數據寫入標準輸出;
重要事實:涉及兩個 shell
首先註意有兩個shell。您在其中工作的外部 Bash,您在
bash <(wget -O - URL)
其中呼叫(類型)。當命令執行時,內部 Bash 作為外部 Bash 的子程序執行。換句話說,外部 Bash 接受
bash <(wget -O - URL)
命令並生成內部 Bash。我會在適當的地方區分這兩者。重要事實:使用 Bash 執行程式碼的方法不止一種
有幾種方法可以讓(內部)Bash 執行一些程式碼:
bash
可以從它的標準輸入讀取程式碼:echo 'date; sleep 2; date' | bash
標準輸入可以是控制台。例如,您通常工作的互動式
bash
從控制台讀取,但它實際上從其標準輸入讀取,因為控制台是它的標準輸入。 2.bash
可以從文件中讀取程式碼:bash /path/to/some/file
(路徑可能是相對的。) 3.
bash
可以從命令行參數讀取程式碼:bash -c 'date; sleep 2; date'
上下文
在評論中你說上下文是這個問題。我在那裡的回答建議更換:
wget -O - URL | bash
和
bash <(wget -O - URL)
第一個命令
bash
從其標準輸入進行內部讀取。您似乎沒有意識到的是,第二個命令bash
從不是其標準輸入的文件中進行內部讀取。會發生什麼
<(…)
當您
bash <(wget -O - URL)
在 Bash 中執行時,外部 Bash 將替換為某個文件<(…)
的路徑。替換後,正在執行的實際命令可能如下所示:bash /dev/fd/63
這會產生內部 Bash。它像打開
/dev/fd/63
一樣打開/path/to/some/file
。多虧了程序替換的“魔力”,
/dev/fd/63
一個管道已經連接到wget -O - URL
.旁注:在
/dev/fd
不可用的系統上,外部 Bash 將使用真正命名的管道(例如/tmp/sh-np.pldKay
)來設置它。相似度
在這兩種情況下,從
wget
到(內部)的連接bash
是相似的。當你執行時wget -O - URL | bash
,bash
從它的標準輸入讀取程式碼,這是一個管道wget
寫入。當您執行時bash <(wget -O - URL)
,bash
從另一個文件(即不是從其標準輸入)讀取程式碼,該文件是管道wget
寫入的。在這兩種情況下,外部 Bash 都會設置管道。區別
不同之處在於程序替換,內部 Bash 的標準輸入不用於將程式碼傳遞給它。標準輸入可以用於其他目的。例如,標準輸入可以是控制台,並且
read
在程式碼中可以從中讀取。回答您的明確問題
- >
發明這個概念是為了解決什麼問題
當命令需要路徑名(文件的路徑)並且您想通過管道輸入內容而不是提供正常文件時,您可以創建命名管道並實現目標。這需要實際創建一個管道 (
mkfifo
),向它輸送一些東西(在後台或另一個控制台中),執行命令並最終刪除命名管道 (rm
)。使用程序替換,Bash 處理管道。這很方便。
- >
什麼過程被取代,用什麼代替?
在語法中替換為某個文件的路徑,然後才執行命令(並且它是
bash <(wget -O - URL)
或類似的)。外部 Bash 準備文件,因此從它讀取意味著讀取(程序)寫入的內容。該文件實際上是一個管道,而不是正常文件。<(wget -O - URL)``bash /dev/fd/63``wget -O - URL
- >
它是否也被命名為“保留標準輸入”,如果是,為什麼?
“保留標準輸入”發生了,但它不是程序替換的替代名稱。這也不是發生的事情的正式名稱。
當您
bash …
在(外部)Bash 中執行(內部)時,內部 Bash 會從外部 Bash 繼承其標準輸入(即,它是同一個文件)。標準輸入可能是控制台。但如果你
wget … | bash …
改為執行,內部 Bash 將看到來自wget
它自己的標準輸入的數據。現在,內部 Bash 的某些部分(例如read
builtin)或內部 Bash 的某些子項可能想要從標準輸入中讀取某些內容。他們期望來自控制台或其他什麼的輸入,而不是內部 Bash 應該執行的程式碼。但是因為內部 Bash 的標準輸入是來自的管道wget
,所以內置程序將使用它,子程序將繼承它作為他們的標準輸入。他們不會繼承外部 Bash 的標準輸入。通過 (inner) 的標準輸入使用程序替換而不是管道程式碼
bash
,您可以使外部 Bash 的標準輸入可用於內部 Bash 的內置函式和子級。您為內部 Bash 的內置函式和子級保留外部 Bash 的標準輸入。同時,您可以保護內部 Bash 讀取和執行的程式碼流不被其內置程序或子程序讀取。這僅是因為
bash
允許您在指定為命令行參數的文件中提供程式碼。如果(內部)Bash 僅支持從標準輸入讀取程式碼,那麼您必須通過其標準輸入提供程式碼。在這種情況下,程序替換無法解決您遇到的問題。