Bash
為什麼管道和重定向與這裡的文件不同?
將重定向與此處文件相結合似乎很合乎邏輯:
$ bash > foo <<EOF echo Hello EOF $ less foo Hello
但是對於管道,它的行為會有所不同:
$ bash | tee foo <<EOF echo Hello EOF $ less foo echo Hello
同樣奇怪的是,如果您立即輸入“歷史”:
$ bash | tee foo <<EOF echo Hello EOF $ history $ history 1 ...
也就是說,第一個命令似乎仍然在新創建的 bash 中。這是怎麼回事?為什麼管道的行為不同?
您正在重定向
tee
’s 的輸入,而不是bash
’s. 採用:bash << EOF | tee foo echo Hello EOF
再舉幾個例子來說明它是如何工作的:
bash << EO1 3<< EO\2 | tee 3<< EO3 foo 4<< EO4 fed (as a deleted temp file open in read-only mode) to bash fd 0 EO1 fed to bash fd 3 without $variable and $(cmd) expansion EO2 fed to tee fd 3 (not that tee does anything with its fd 3) EO3 fed to tee fd 4 (see how, like any redirection operator 3<< END can appear anywhere on the command line (for simple commands at least)) EO4
重定向複合命令:
{ head -n2; wc -l; } << EOF fed as fd 0 for the whole command group $(ps -e) EOF
或者:
if head -n1; then head -n2 fi << EOF 1 2 3 EOF
您可以重複使用相同的結束標記:
$ ls -l /proc/self/fd << E 3<< E >&2 | 3<< E 4<< E ls -l /proc/self/fd pipe heredoc> E pipe heredoc> E pipe heredoc> E pipe heredoc> E total 0 lr-x------ 1 stephane stephane 64 Feb 24 12:50 0 -> /tmp/zshLiVzp3 (deleted) lrwx------ 1 stephane stephane 64 Feb 24 12:50 1 -> /dev/pts/5 lrwx------ 1 stephane stephane 64 Feb 24 12:50 2 -> /dev/pts/5 lr-x------ 1 stephane stephane 64 Feb 24 12:50 3 -> /tmp/zshFLbQ7T (deleted) lr-x------ 1 stephane stephane 64 Feb 24 12:50 4 -> /proc/25749/fd/ total 0 lr-x------ 1 stephane stephane 64 Feb 24 12:50 0 -> pipe:[70735808] lrwx------ 1 stephane stephane 64 Feb 24 12:50 1 -> /dev/pts/5 lrwx------ 1 stephane stephane 64 Feb 24 12:50 2 -> /dev/pts/5 lr-x------ 1 stephane stephane 64 Feb 24 12:50 3 -> /tmp/zshL3KBp3 (deleted) lr-x------ 1 stephane stephane 64 Feb 24 12:50 4 -> /tmp/zshcJjS7T (deleted) lr-x------ 1 stephane stephane 64 Feb 24 12:50 5 -> /proc/25748/fd/
至於為什麼第一個
history
命令在那個新bash
的 in 中執行:$ bash | tee foo <<EOF echo Hello EOF $ history $ history 1 ...
那是因為
bash
stdin 仍然是終端,但它的 stdout 是一個死管道(在管道的另一端,tee
已從該刪除臨時文件重定向其 stdin,因此該管道的讀取端已關閉)。
bash
不會寫它的提示或您在其標準輸出(死管道)上鍵入的內容的迴聲,而是寫到終端,這樣bash
您就可以history
在第一個提示下輸入。但是,那個
history
(這是一個內置的,由bash
程序執行,而不是子程序)會將其輸出寫入該死管道。這樣做時,該bash
程序將收到一個 SIGPIPE 信號(因為沒有閱讀器)並死亡。下一個提示將由呼叫 shell 發出。