Bash
將 stderr 全域重定向到 /dev/null 後的不可見提示
學習TLDP 的 Advanced Bash-Scripting Guide我無法從 tty 和 pts 在 debian 9 的 bash 4.4.12 中重建以下 shell 輸出:
bash$ lsof -a -p $$ -d0,1,2 COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME bash 363 bozo 0u CHR 136,1 3 /dev/pts/1 bash 363 bozo 1u CHR 136,1 3 /dev/pts/1 bash 363 bozo 2u CHR 136,1 3 /dev/pts/1 bash$ exec 2> /dev/null bash$ lsof -a -p $$ -d0,1,2 COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME bash 371 bozo 0u CHR 136,1 3 /dev/pts/1 bash 371 bozo 1u CHR 136,1 3 /dev/pts/1 bash 371 bozo 2w CHR 1,3 120 /dev/null
每當我執行第二個命令時,shell 提示符就會消失,並且所有鍵盤輸入都停止顯示,儘管我仍然可以執行命令並查看它們的輸出。這是為什麼?
這是因為您重定向了 shell 的標準錯誤。
根據標準,這就是符合 POSIX 的 shell 應該編寫其互動式提示的地方。
- Bourne Again、Heirloom Bourne、(Debian和FreeBSD)93 Korn、MirBSD Korn、(FreeBSD、OpenBSD 和Debian)PD Korn、(FreeBSD和Debian)Almquist 和Watanabe shell 在這方面都符合要求,並將它們的互動式提示寫入標準錯誤。你會發現他們都缺乏及時的行為。
然而,不回顯輸入行為要復雜得多:
- Debian PD Korn、Debian Almquist 和 Heirloom Bourne shell 沒有實現它們自己的行編輯器,而是依賴於核心中終端行規則提供的編輯器。您仍然會看到回顯您鍵入的內容作為他們的標準輸入。
- Watanabe、(FreeBSD 93) Korn 和 (Debian 93) Korn shell 實現了它們自己的行編輯器,當它們(重新)顯示正在編輯的輸入行時,它們也會寫入標準錯誤。但是,他們在執行命令之前打開了終端回顯,
exec
並且(因為標準錯誤不再是終端設備)在為他們的下一個輸入呼叫行編輯器時*無法再次關閉它。*因此,即使來自 shell 行編輯器的輸入回顯將轉到現在重定向的標準錯誤,您也會看到您鍵入的更多輸入由終端行規則回顯。他們的行編輯器也會以微妙的方式出錯,例如無法辨識任何進一步的終端尺寸變化。- MirBSD Korn、(FreeBSD PD) Korn 和 (OpenBSD PD) Korn shell 實現了它們自己的行編輯器,它們(重新)將已編輯的行顯示為標準錯誤,但直接打開另一個文件描述符
/dev/tty
以控制終端回顯等內容. 在為下一個輸入呼叫行編輯器時,他們成功地再次關閉了迴聲。因此,您將不會看到您鍵入的進一步輸入由他們的行編輯器或終端行規則回顯。- Bourne Again 和 FreeBSD Almquist shell 實現了它們自己的行編輯器,它們(重新)將已編輯的行顯示為標準錯誤,但使用標準輸入來控制諸如終端回顯之類的東西。在為下一個輸入呼叫行編輯器時,他們成功地再次關閉了迴聲。因此,您將不會看到您鍵入的進一步輸入由他們的行編輯器或終端行規則回顯。
BusyBox Almquist和Z shell 在這方面不符合 POSIX。他們都實現了自己的行編輯器。通過這兩種方法,您將看到該附錄使您相信會發生的行為。
- BusyBox Almquist shell 的行編輯器使用標準輸出作為輸入回顯,這也是它編寫提示的地方。它根本不受標準錯誤重定向的影響。但是您可以通過重定向標準輸出來獲得效果。它使用標準輸入來辨識終端尺寸的變化。
- Z shell 努力嘗試找到一個終端設備來執行 ZLE,直到並包括顯式打開
/dev/tty
. 它在啟動時將文件描述符複製到終端設備,然後 ZLE 將其用於所有內容;用於回顯鍵入的輸入、讀取鍵入的輸入、寫入互動式提示以及打開和關閉終端回顯。因此,ZLE 不受標準錯誤、輸出甚至輸入的後續重定向的影響。如果您願意,您可以將所有三個重定向到/dev/null
,exec
Z shell 仍會以互動方式提示您並接收輸入。(Thompson shell 首先不支持 shell
exec
命令機制,因為它早於它的發明。)你應該向作者 Stéphane Chazelas 抱怨那個附錄是錯誤的,這樣它可能會得到修復。
進一步閱讀
- “外殼變數”。 殼牌和實用程序。基本規格。IEEE 1003.1:2017。公開組。2017 年。
- https://unix.stackexchange.com/a/299440/5132