我是shell腳本的noob。如果命令失敗,我想打印一條消息並退出我的腳本。我試過了:如何在命令失敗時退出?
my_command && (echo 'my_command failed; exit)
但它不起作用。它會繼續執行腳本中此行後面的指令。我使用Ubuntu和bash。
我是shell腳本的noob。如果命令失敗,我想打印一條消息並退出我的腳本。我試過了:如何在命令失敗時退出?
my_command && (echo 'my_command failed; exit)
但它不起作用。它會繼續執行腳本中此行後面的指令。我使用Ubuntu和bash。
嘗試:
my_command || { echo 'my_command failed' ; exit 1; }
四改:
&&
到||
{ }
代替()
;
後exit
個{
之後和之前}
既然你要打印的消息並退出,只有當命令失敗(退出時非零值),你需要一個||
不是&&
。
cmd1 && cmd2
將運行時cmd2
cmd1
成功(退出值0
)。凡爲
cmd1 || cmd2
將運行cmd2
時cmd1
失敗(退出值不爲零)。
使用()
使它們內部的命令在子shell運行,並調用exit
從那裏使你退出子殼,而不是原來的殼,從而繼續執行在原來的殼。
爲了克服這種使用{ }
bash所需要的最後兩個變化。
它看起來似乎是「顛倒過來」。如果函數「成功」,則返回0,如果「失敗」,則返回非零值,因此&&可能需要在前半部分返回非零值時計算。 這並不意味着上面的答案是不正確的 - 不,它是正確的。&&和||在腳本中基於成功而不是返回值。 – CashCow 2012-07-20 10:43:50
看起來相反,但讀出來,它是有道理的:「做這個命令(成功)」或「打印此錯誤並退出」 – simpleuser 2014-03-14 22:18:36
它的邏輯是該語言使用短路評估(SCE)。對於SCE,f表達式的形式爲「p OR q」,並且p被評估爲真,那麼沒有理由甚至不需要q。如果表達式的形式爲「p AND q」,並且p被評估爲false,則沒有理由查看q。其原因有兩方面:1)速度更快,原因很明顯,2)避免了某些類型的錯誤(例如:「如果x!= 0 AND 10/x> 5」在沒有SCE時會崩潰)。像這樣在命令行中使用它的能力是一個令人愉快的副作用。 – user2635263 2015-07-11 00:01:34
提供my_command
是規範設計的,即成功返回0,則&&
正好與你想要的相反。你想要||
。
另外請注意,(
似乎不適合我在bash中,但我不能嘗試從我的位置。告訴我。
my_command || {
echo 'my_command failed' ;
exit 1;
}
IIRC,在{} – 2010-09-29 14:35:42
@Alex中的每一行後面都需要分號:如果它們在單獨的行上,則不需要分號。 – 2010-09-29 15:47:28
另請注意,每個命令的退出狀態都存儲在shell變量$?中,您可以在運行該命令後立即檢查該變量。非零狀態表示失敗:
my_command
if [ $? -eq 0 ]
then
echo "it worked"
else
echo "it failed"
fi
這可以替換爲my_command,這裏不需要使用test命令。 – 2010-09-29 14:53:51
+1,因爲我認爲你不應該因爲列出這個替代品而受到懲罰 - 它應該放在桌面上 - 雖然它有點難看,而且根據我的經驗,在其中間運行另一個命令時不會注意到測試的本質(也許我很容易只是愚蠢的)。 – 2010-09-30 08:34:32
@BartSas如果命令很長,最好把它放在自己的路線上。它使腳本更具可讀性。 – Michael 2012-08-13 19:45:28
其他的答案已經涵蓋了直接的問題很好,但你也可能有興趣使用set -e
。因此,任何失敗的命令(例如if
測試以外的特定上下文)都將導致腳本中止。對於某些腳本,它非常有用。
我砍死了下面的語句:
echo "Generating from IDL..."
idlj -fclient -td java/src echo.idl
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi
echo "Compiling classes..."
javac *java
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi
echo "Done."
前面加上一個資料回聲每個命令,並按照每個命令與相同
if [ $? -ne 0 ];...
線。 (當然,你可以,如果你想要編輯的錯誤消息。)
這可以被定義爲一個函數,從而重用它。 – 2017-03-15 12:46:34
如果你想在你的腳本中的所有命令該行爲,只需添加
set -e
set -o pipefail
在腳本的開始。這一對選項告訴bash解釋器在一個命令返回非零退出代碼時退出。
雖然這不允許您輸出退出消息。
您可以使用'trap' bash內置命令在退出時運行命令。 – 2014-04-12 18:07:53
這是X-Y問題的答案。 – jwg 2015-11-06 16:14:47
可能有趣的是解釋哪些命令獨立執行而不是配對。特別是因爲'set -o pipefail'可能不是所需的行爲。仍然感謝您指出! – 2017-01-26 10:49:29
對於防錯你的命令:
execute [INVOKING-FUNCTION] [COMMAND]
execute() {
error=$($2 2>&1 >/dev/null)
if [ $? -ne 0 ]; then
echo "$1: $error"
exit 1
fi
}
在精益製造啓發:
您也可以使用,如果你想保留退出錯誤狀態,並且有一個可讀的文件,每行一個命令:
my_command1 || exit $?
my_command2 || exit $?
但是,這不會打印任何其他錯誤消息。但是在某些情況下,無論如何,錯誤將由失敗的命令打印。
trap
shell內建允許捕獲信號以及其他有用的條件,包括失敗的命令執行(即非零返回狀態)。所以如果你不想明確地測試每一個命令的返回狀態,你可以說trap "your shell code" ERR
,並且任何時候一個命令返回一個非零狀態都會執行shell代碼。例如:
trap "echo script failed; exit 1" ERR
注意的是,與捕獲失敗的命令的其它情況下,管道,需要特殊處理;以上將不會趕上false | true
。
您是否打算將未封閉的引用作爲會導致失敗/退出的語法錯誤?如果沒有,你應該關閉你的例子中的報價。 – hobs 2015-12-29 18:02:02