Bash

Bash:抑制後重新打開stderr

  • November 28, 2018

我製作了這個腳本,它可以自動安裝/解除安裝 git。在我的測試是否安裝了 git 的函式中,我使用git --version命令並測試返回碼。

我不喜歡正常出現的 stderr 輸出,因為我正在嘗試製作一個不錯的自定義輸出。儘管我已經想出瞭如何僅為此功能抑制 stderr,但我似乎無法重新啟動它。

呼叫此函式後,我的read提示現在失去了。

function CheckGit() {
   exec 3>&2           # link file desc 3 w/ stderr
   exec 2> /dev/null

   SILENT_MODE=$1

   if [[ ! $(git --version) ]]; then
       if [ SILENT_MODE ]; then
           printf "${LT_RED} GIT IS NOT INSTALLED.\n"
       fi
       continue;
   else
       if [ SILENT_MODE ]; then
           printf "${LT_BLUE} GIT IS CURRENTLY INSTALLED.\n"
       fi
       continue;
   fi
   GIT_INSTALLED=$?
   #turn back on the stderr notifications
   exec 2>&3 3>&-      # Restore stdout and close file descriptor #3
}

while true; do
   printf "${LT_BLUE} Menu\n"
   printf " ***********************************************\n"
   printf "${LT_GREEN} a) Check git.\n"
   printf "${LT_GREEN} b) (More to be added)\n"
   printf "${LT_GREEN} c) ...\n"
   printf "${LT_GREEN} d) ...\n"
   printf "${LT_GREEN} h) ...\n"
   printf "${LT_RED} x) Exit.\n"
   printf "\n${NC}"
   read -p "Please make a selection: " eotuyx
   case $eotuyx in
       [Aa]* ) CheckGit true; continue;;
       [Bb]* ) ...; continue;;
       [Cc]* ) ...; continue;;
       [Dd]* ) ...; continue;;
       [Hh]* ) ...; continue;;
       [XxQq]* ) break;;
       * ) -e "\n${NC}" + "Please answer with a, b, c, d, x(or q).";;
   esac
done

重申評論中給出的建議:

  1. 從函式中

刪除continue語句。CheckGit

  • 它們不是必需的,
  • 而且——你可能沒有意識到——它們不僅會導致(從函式)立即返回到主循環,而且會立即返回到while true主循環頂部的語句。因此,正如Tomasz 指出的那樣,您的exec 2>&3 3>&-語句沒有被執行。

一般注意事項:

  1. if [ SILENT_MODE ]正如mosvy 指出的那樣,它總是正確的,因為它只是測試字元串SILENT_MODE是否為非空。你似乎想要if [ "$SILENT_MODE" ]
  2. 但你可能在自欺欺人。  if [ "$SILENT_MODE" ]是真的,即使$SILENT_MODEfalse——它所做的只是測試字元串是否為非空,所以呼叫CheckGit false 仍然會導致資訊被顯示。
  3. 而且,即使您沒有欺騙自己,您也可能欺騙了下週必須維護此腳本的人。而且,是的,那個人可能就是你。您的明顯邏輯是“如果處於靜默模式,請報告額外資訊”。這在邏輯上是倒退的;說起來會更有意義if [ "$SILENT_MODE" = false ],或者呼叫變數VERBOSE_MODE
  4. $?非常短暫。它始終是最新命令的結果。  所以,如果你這樣做
if *檢查是否安裝了 git*;然後
printf "GIT 未安裝。\n"
別的
printf "GIT 已安裝。\n"
是
GIT_INSTALLED=$?

然後GIT_INSTALLED獲取printf. 您需要提前設置GIT_INSTALLED。 6. 您的測試,,if [[ ! $(git --version) ]]; then測試,而不是“返回碼”(正如您在問題中所說),而是是否git --version將任何內容寫入標準輸出。這可能是你想要的。這可能是測試是否git安裝的最佳方法。但是檢查命令的退出狀態可能會更好(通常通常更好)。 7. 風格說明:如果“真實”部分在前,我發現if- then-else陳述更容易理解。你的腳本說

如果沒有安裝 git
然後
說沒有安裝
否則(即,如果***未***安裝)
說它已安裝
是

雙重否定令人困惑。 8. 而且,是的;exec 2> /dev/null如果您想從連續 42 條語句中抑制標準錯誤,這很方便。如果您只需要影響單個命令,只需將2> /dev/null (或> /dev/null 2>&1)放在該命令上,就像mosvy 建議的那樣。

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