Pipe

為什麼在某些情況下我無法重定向輸出

  • July 7, 2020

例如

# this line should output ssh banner
nc localhost 22
# this line should output the same string expect the replacements
nc localhost 22|sed 's/SSH/XXX/g'

nc localhost 22 > foo # after killing the process, I can see the banner in file `foo`
nc localhost 22|sed 's/SSH/XXX/g' > foo # however I see nothing when sed is used

如前所述,如果我使用sed管道nc傳輸 ’ 的輸出,則sed’ 的輸出無法重定向到文件。

而且我還嘗試了其他命令來管道結果,例如grep, tr,相同的結果。

但是,cat可以將結果通過管道傳輸到文件中。奇怪的..

nc localhost 22|cat > foo

那麼為什麼會這樣呢?cat在這種情況下,和其他命令有什麼區別?如何使sed輸出重定向到文件cat

$ 貓 | sed -e 's/foo/bar/' > output.txt
富
^C
$ 貓輸出.txt
*[沒有什麼]*

但:

$ 貓 | sed -e 's/foo/bar/' > output.txt
富
*^D*
$ 貓輸出.txt
酒吧

寫入文件——但不寫入終端——通常由 C 庫(stdio 函式)緩衝到幾千字節的塊。如果您按 Ctrl-C 來終止管道,sed則在其終止之前將沒有時間寫出緩衝區,因此生成的輸出文件為空。(你可以說這是 C 庫中的一個錯誤,它沒有擷取終止信號,但它確實如此。)

Plaincat可能不使用 stdio,因為它不處理像線條這樣複雜的東西。類似的東西cat -n可能會有所不同,也可能不會。

您可以安排這樣您就不需要使用 Ctrl-C 來終止管道,而是讓它自己完成。至少在 my 中nc,該-qN選項告訴它在標準輸入關閉後N秒後退出,例如:

$ printf '' | nc -q0 localhost 22 | sed 's/SSH/FOO/' > output.txt 
$ cat output.txt 
FOO-2.0-OpenSSH_7.4p1 Debian-10+deb9u7

或者,至少有幾種方法可以關閉緩衝,請參閱例如 關閉管道中的緩沖和 unbufferstdbuf 以刪除標準輸出緩衝?

GNU sed 也有-u/--unbuffered開關

從輸入文件中載入最少量的數據並更頻繁地刷新輸出緩衝區

引用自:https://unix.stackexchange.com/questions/597242