config.status
我引用了生成的下一個程式碼片段configure
。
if test ! -f "$as_myself"; then
{ { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
{ (exit 1); exit 1; }; }
fi
程式碼片段中,{ (exit 1); exit 1; };
做了什麼?只exit
在子 shell 中執行的目的是什麼?
答案1
執行(exit 1);
是觸發陷阱最簡單的方法ERR
。如果set -e
有效,它也會觸發立即退出。 (觸發錯誤條件需要命令失敗;exit
子 shell 中的失敗值會導致子 shell 失敗。)
exit 1;
不會做這兩件事。
So{(exit 1); exit 1;}
可用於先產生ERR
陷阱,這可能會執行一些對偵錯有用的操作,然後終止腳本並顯示錯誤指示。
autoconf
但文件中的情況並非如此。autoconf
腳本依靠EXIT
陷阱來清理運行期間創建的臨時檔案。大多數 shell(包括)將在呼叫陷阱之前bash
根據命令中提供的值設定狀態。這可以允許陷阱檢測它是從錯誤還是正常終止中調用,並且還允許它確保在陷阱操作結束時正確設置退出狀態。exit
EXIT
EXIT
然而,顯然有些外殼不合作。這是來自autoconf
手動的:
某些 shell 腳本(例如由 產生的腳本
autoconf
)在退出前使用陷阱進行清理。如果最後一個 shell 指令以非零狀態退出,則陷阱也會以非零狀態退出,以便呼叫者可以知道發生了錯誤。不幸的是,在某些 shell(例如 Solaris)中
/bin/sh
,退出陷阱會忽略 exit 指令的參數。在這些 shell 中,陷阱無法確定它是由普通退出呼叫還是由退出 1 呼叫AC_MSG_ERROR
。
解決方法是確保$?
具有退出狀態前該exit
命令被執行,因此當EXIT
陷阱執行時它肯定會具有該值。事實上,正是這個AC_MSG_ERROR
巨集插入了奇怪的程式碼,並帶有多餘的大括號。
答案2
據我所知,這樣做沒有任何目的,沒有什麼可以透過啟動子shell然後立即退出來直接實現。
像這樣的事情很可能是自動產生程式碼的副作用 - 在某些情況下,可能會在子 shell 中執行其他命令,而這些命令是有意義的exit 1
。最終,透過允許產生程式碼插入一些在某些情況下沒有任何功能的語句,產生程式碼很有可能在某種程度上得到簡化,而每次產生「乾淨的程式碼」會更加複雜。要嘛是那個,要嘛是產生上述程式碼的程式碼寫得不好:)
自由使用{...}
是另一個例子,它們中的大多數都是多餘的,但是編寫在每種情況下插入它們的程式碼更容易(也許在某些情況下您想要重定向區塊的輸出/輸入)而不是區分那些不需要的地方並省略它們。
答案3
(exit 1)
是一種簡單的、可能是最簡單的獲取特定退出代碼的方法(當然,在 1 的特殊情況下,還有更簡單的方法)。但這不是本例的原因,因為沒有檢查退出代碼。
放入子 shell 的目的exit
可能是不退出腳本(儘管使用 exit 來產生特定的退出代碼)。