當第一個腳本中呼叫的腳本以錯誤程式碼退出時,如何繼續執行腳本?
我正在嘗試編寫一個 bash 腳本,該腳本將重複執行第二個腳本,直到它失敗並擷取第二個腳本的標準輸出和標準錯誤。我已經設法處理了這個過程中遇到的大多數問題,並最終得到了這個腳本(稱為
error_checker.sh
):#!/usr/bin/env bash i=0 while [ $? -ne 1 ] do i=$[$i+1] source script.sh &> log.txt echo "This error occurred after $i run(s)." >> log.txt done
我想重複重複的腳本被稱為
script.sh
,並且具有以下程式碼:#!/usr/bin/env bash n=$(( RANDOM % 100 )) if [[ n -eq 42 ]]; then echo "Something went wrong" >&2 echo "The error was using magic numbers" exit 1 fi echo "Everything went according to plan"
該
error_checker.sh
腳本可以將失敗執行的 stdout 和 stderr 輸出到指定文件 log.txt,但隨著該腳本與該行的第二個腳本一起退出source script.sh &> log.txt
因此,我無法將其他錯誤消息附加到該文件。
我已經搜尋了一段時間,發現這可能與執行第二個腳本時創建子shell有關,這可能會解決問題,但我只是無法讓腳本執行使用
./
而不是source
. 如果我更改source
為./
,當我輸入 時,整個終端就會凍結./error_checker.sh
。非常感謝任何幫助!
更新: 感謝目前的答案!我認為現在我的主要問題是,當我更改
source script.sh
為./script.sh
在error_checker.sh
新的 shell 程序中執行它時,整個終端都凍結了,這使我無法使用./
. 這就是為什麼我只能error_checker.sh
在使用source script.sh
. 任何想法發生了什麼?更新二: 我改
source
了./
,發現雖然整個終端好像當機了,我不得不按ctrl+c來結束程序,它仍然可以生成一個log.txt。但是,雖然 using 的版本source
會生成一個 log.txtSomething went wrong. The error was using magic numbers
,這表明 stdout 和 stderr 是由 using 擷取的&>
,但 using 的版本會./
生成一個 log.txt 的說法Everything went according to plan. The error occurred after X run(s)
。知道發生了什麼嗎?最後更新:我已經根據 Glenn 對以下內容的回答編輯了我的程式碼,它執行良好。似乎 while 循環中的 echo 命令阻止了我實際評估 script.ph 的退出狀態,從而創建了一個無限循環。
#!/usr/bin/env bash i=0 while [ $? -ne 1 ] do ((i++)) ./script.sh >& log.txt done echo "This error occurred after $i run(s)." >> log.txt
因為您正在採購腳本,所以更改
exit 1
為return 1
如果您還計劃將 script.sh 作為“頂級”腳本執行,您可以執行
if (( n == 42 )); then if [[ "$0" == "${BASH_SOURCE[0]}" ]]; then # I'm the "main" script exit 1 else # I'm being sourced from some other script return 1 fi fi
如果您必須使用
source
(我對此表示懷疑,但我們必須查看程式碼)並且您無法更改該腳本,那麼您必須在子 shell 中執行 source 命令。這意味著exit
將退出子shell,而不是執行頂層程序的目前shell:i=0 # /--------------------------------\ parentheses create a subshell while (source script.sh >> log.txt 2>&1) do ((i++)) done echo "This error occurred after $i run(s)." >> log.txt
這將創建一個日誌文件,其中包含:
Everything went according to plan ... Everything went according to plan Something went wrong The error was using magic numbers This error occurred after 302 run(s).
關於您的程式碼的一些註釋:
$[...]
是未記錄的語法,可能已棄用。用於$((...))
算術擴展或((...))
算術評估。$?
是前一個命令的退出狀態,對於 while 循環的第二次迭代,它是echo
. 由於echo
僅在無法寫入標準輸出(或指定的文件描述符)時返回非零,因此您有一個無限循環*,因為您沒有測試 script.sh 的退出狀態!*
- 在出現錯誤情況後,您有大約 100 分之一的機會按下 Ctrl+C,因此 99% 的時間日誌文件將包含“好”消息”
&>
不是慣用語:使用>& file
或更明顯的>file 2>&1
.- 您很可能希望在循環外列印“錯誤發生在…之後”消息