在要執行的shell腳本中,我可以使用set -e
來中止錯誤。Bash:在源腳本中出錯時停止
但是,在源腳本中,如果稍後的命令以錯誤狀態退出,則使用set -e
將終止原始shell。
source set_e.sh
./exit_1.sh
# shell dies
一個平凡的解決辦法是set +e
在腳本的末尾,但是這樣會破壞父母的set -e
如果使用的話(如果有人包裝我的腳本,將來這很可能發生)。
如何在源腳本中獲得異常中止功能?
在要執行的shell腳本中,我可以使用set -e
來中止錯誤。Bash:在源腳本中出錯時停止
但是,在源腳本中,如果稍後的命令以錯誤狀態退出,則使用set -e
將終止原始shell。
source set_e.sh
./exit_1.sh
# shell dies
一個平凡的解決辦法是set +e
在腳本的末尾,但是這樣會破壞父母的set -e
如果使用的話(如果有人包裝我的腳本,將來這很可能發生)。
如何在源腳本中獲得異常中止功能?
如果errexit選項設置在源腳本的開頭並在源腳本結尾恢復其原始值,則可以通過set -o
進行檢測。
您可以檢查是否set -e
已經啓用,並有條件地設置其算賬:
[[ $- == *e* ]] && state=-e || state=+e
set -e
yourcode
set "$state"
但是請注意,這是set -e
車和腳本不應該依賴於它的正確性。例如,如果有人源腳本在if
聲明,set -e
可能無法再正常工作:
ls: cannot access file.that.doesnt.exist: No such file or directory
Success
Done
同時:
echo '
set -e
ls file.that.doesnt.exist
echo "Success"
' > yourscript
set -e
if ! source yourscript
then
echo "Initialization failed"
fi
echo "Done"
然後set -e
將不再失敗在bash 30年3月4日中止在yourscript
它將在bash 2,3和4.2中退出整個腳本:
ls: cannot access file.that.doesnt.exist: No such file or directory
第二部分是誤導 - 如果'yourscript'設置'errexit',封裝代碼將確實在其內部的錯誤上放棄(用bash 4.2.x測試)。與常規使用shell if-then-else相比,這看起來可能與直覺相反,但如果您正在尋找不可靠的代碼,那麼期望您將它包裝在子外殼中似乎並不合理。 –
@JosipRodin我看到bash 2和3中止了整個腳本,但在4.3.30(1) - 釋放它不能中止所描述的。有趣的是,知道這種行爲已經發生了很大的變化。 –
好抓。我認爲目前的行爲與主要建議一致 - 使用子shell。例如,如果你這樣做:'set + e; (。yourscript);如果[$? -ne 0];然後回顯「初始化失敗」; fi' - 結果相當合理。 –
更改set -e
到return 0
(或選擇您喜歡的整數而不是0
)。你可以把它看作是一個函數來處理你的源文件。例如:
$ cat myreturn.sh
#!/bin/bash
let i=0
while test "$i" -lt 10; do
echo "i $i"
if test "$i" -gt 5 ; then
return 5
fi
sleep 1
((i+=1))
done
return 4
$ (. myreturn.sh)
i 0
i 1
i 2
i 3
i 4
i 5
i 6
$ echo $?
5
爲什麼這個答覆不是第一個呢?非常感謝!! – eplaut
這是不可能的。然而,如果你願意,你可以選擇使用子shell:
(
set -e
source another.sh
)
只有調用腳本的環境永遠不能被調用的腳本改變。
注意:使用換行符分隔兩個命令而不使用分號可能很重要。
嗯,這個問題不是很清楚重:
您可以設置:原作者攔截錯誤執行的腳本,但是,作爲一個切入點解決以下就足夠了之後想要什麼在ERR上捕獲並處理源腳本中的錯誤。以下是兩種情況:一種源腳本使用「set -e」,另一種腳本不使用「set -e」。
主腳本調用具有定義的「設置-e」和捕獲差錯的次級腳本:
[galaxy => ~]$ cat primary.sh
#!/bin/sh
set -e
echo 'Primary script'
trap 'echo "Got an error from the secondary script"' ERR
source secondary.sh
trap - ERR
echo 'Primary script exiting'
[galaxy => ~]$ cat secondary.sh
#!/bin/sh
echo 'Secondary script'
set -e
echo 'Secondary script generating an error'
false
echo 'Secondary script - should not be reached'
[galaxy => ~]$ ./primary.sh
Primary script
Secondary script
Secondary script generating an error
Got an error from the secondary script
[galaxy => ~]$
主腳本調用腳本次級沒有「設置-e」和捕獲錯誤:
[galaxy => ~]$ cat primary.sh
#!/bin/sh
set -e
echo 'Primary script'
trap 'echo "Got an error from the secondary script"' ERR
source secondary.sh
trap - ERR
echo 'Primary script exiting'
[galaxy => ~]$ cat secondary.sh
#!/bin/sh
echo 'Secondary script'
echo 'Secondary script generating an error'
false
echo 'Secondary script - should not be reached if sourced by primary.sh'
[galaxy => ~]$ ./primary.sh
Primary script
Secondary script
Secondary script generating an error
Got an error from the secondary script
[galaxy => ~]$
作爲獎勵:在被執行的腳本攔截錯誤並繼續:
[galaxy => ~]$ cat primary.sh
#!/bin/sh
echo 'Primary script'
i=0
while [ $i = 0 ]; do
i=1
trap 'echo "Got an error from the secondary script"; break' ERR
source secondary.sh
done
trap - ERR
echo 'Primary script exiting'
[galaxy => ~]$ cat secondary.sh
#!/bin/sh
echo 'Secondary script'
echo 'Secondary script generating an error'
false
echo 'Secondary script - should not be reached if sourced by primary.sh'
[galaxy => ~]$ ./primary.sh
Primary script
Secondary script
Secondary script generating an error
Got an error from the secondary script
Primary script exiting
[galaxy => ~]$
@BlueMoon OP的帖子解釋了爲什麼不行。 –
難道你不能在呼叫環境中設置退出陷阱並在那裏處理它? –