簡體   English   中英

為什么在bash中將stdin重定向到while循環中?

[英]Why redirect stdin inside a while read loop in bash?

請考慮以下示例腳本:

#!/bin/sh

do_something() {
    echo $@
    return 1
}

cat <<EOF > sample.text
This is a sample text
It serves no other purpose
EOF

cat sample.text | while read arg1 arg2 arg3 arg4 arg5; do
    ret=0
    do_something "$arg1" "$sarg2" "$arg3" "$arg4" "$arg5" <&3 || ret=$?
done 3<&1

stdout重定向為filedescriptor 3的輸入的目的是什么? 至少在Bash ,如果省略它似乎沒有任何區別。 如果它在bash之外的任何其他shell中執行會有什么影響嗎?

UPDATE

對於那些想知道它來自何處的人來說,它是來自Debian的cryptdisks_start腳本的簡化示例。

這里明確的意圖是通過確保其stdin來自其他地方來阻止do_somethingsample.text流中讀取。 如果您在使用或不使用重定向時沒有看到行為上的差異,那是因為do_something實際上並未在測試中從stdin讀取。

如果你同時從同一個流中readdo_something讀取,那么do_something消耗的任何內容將無法用於后續的read實例 - 當然,你有非法內容輸入到do_something ,結果在諸如加密密鑰被嘗試的后果中(如果真實世界的用例類似於cryptmount ),&c。

cat sample.text | while read arg1 arg2 arg3 arg4 arg5; do
    ret=0
    do_something "$arg1" "$sarg2" "$arg3" "$arg4" "$arg5" <&3 || ret=$?
done 3<&1

現在,它是錯誤的 - 3<&1是不好的做法,而3<&0 ,因為它假設沒有基礎,stdout也可以用作輸入 - 但它確實成功實現了這一目標。


順便說一句,我會寫更多如下:

exec 3</dev/tty || exec 3<&0     ## make FD 3 point to the TTY or stdin (as fallback)

while read -a args; do           ## |- loop over lines read from FD 0
  do_something "${args[@]}" <&3  ## |- run do_something with its stdin copied from FD 3
done <sample.text                ## \-> ...while the loop is run with sample.txt on FD 0

exec 3<&-                        ## close FD 3 when done.

它有點冗長,需要顯式關閉FD 3,但這意味着如果我們運行stdout連接到FIFO(或任何其他只寫接口)的只寫端,我們的代碼就不會再被破壞了而不是直接到TTY。


至於這種做法阻止的錯誤,這是一個非常常見的錯誤。 請參閱以下有關它的StackOverflow問題:

等等

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM