Shell-Script
Shell:兩個命令的STDIN/STDOUT的相互管道
當我們使用 POSIX shell 執行它時,
$ cmd0 | cmd1
cmd0 的 STDOUT 通過管道傳送到 cmd1 的 STDIN。
問:除此之外,如何將 cmd1 的 STDOUT也通過管道傳輸到 cmd0 的 STDIN?
是否必須使用從/到命名管道(FIFO)的重定向?我不太喜歡命名管道,因為它們佔用了一些文件系統路徑,我需要擔心名稱衝突。還是我必須通過 C、Python 或一些通用程式語言呼叫 pipe(2)?
(cmd0 和 cmd1 都做一些網路 I/O,所以它們不會永遠互相阻塞。)
在具有雙向管道(不是 Linux)的系統上,您可以執行以下操作:
cmd0 <&1 | cmd1 >&0
在 Linux 上,您可以執行以下操作:
: | { cmd1 | cmd2; } > /dev/fd/0
這是有效的,因為在 Linux(和 Cygwin,但通常不是其他系統)
/dev/fd/x
上,x
管道(命名或未命名)的 fd 就像命名管道一樣,也就是說,以讀取模式打開它可以獲得讀取端和寫入模式讓你寫作結束。使用
yash
shell及其x>>|y
管道重定向運算符:{ cmd0 | cmd1; } >>|0
- zsh:
coproc cmd0 cmd1 <&p >&p
- 克什
cmd0 |& cmd1 <&p >&p
- bash4+
coproc cmd0 cmd1 <&"${COPROC[0]}" >&"${COPROC[1]}"
專用工具方法(無恥地從這個非常相似的問題的答案中複製):
使用
pipexec
pipexec [ A /path/to/cmd0 ] \ [ B /path/to/cmd1 ] \ '{A:1>B:0}' '{A:0>B:1}'
或使用
dpipe
dpipe cmd0 = cmd1
或使用
socat
:socat EXEC:cmd0 EXEC:cmd1,nofork # using socketpairs socat EXEC:cmd0,commtype=pipes EXEC:cmd1,nofork # using pipes
我不知道
python
,但這也相對容易完成perl
:perl -e 'pipe STDOUT,STDIN; exec "cmd0 | cmd1"'
您也可以隨時使用命名管道,但是為它們找到唯一的名稱以及在其中創建它們的一些安全目錄,限制對它們的訪問(因此其他程序無法打開它們並進行干預)以及之後的清理成為難以解決的額外問題可靠且便攜地克服。
無論如何,當心死鎖!