2012-09-08 40 views
6

下面是我在bash中執行的腳本。它工作正常。如何處理shell腳本中的錯誤/異常?

fileexist=0 
for i in $(ls /data/read-only/clv/daily/Finished-HADOOP_EXPORT_&processDate#.done); do 
    mv /data/read-only/clv/daily/Finished-HADOOP_EXPORT_&processDate#.done /data/read-only/clv/daily/archieve-wip/ 
    fileexist=1 
done 

問題陳述: -

在我擁有使用cron job爲每天運行上面的shell腳本,我沒有任何error/exception handling mechanism。假設有任何錯誤,那麼我不知道發生了什麼?

由於上述腳本執行後,有some other scripts that will be dependent on the data provided by above script,所以我總是得到其他人的抱怨,這些人依賴於我的腳本數據發生了錯誤。

那麼在腳本中有什麼方法可以get notified if anything wrong has happened?假設如果cluster is having some maintenance和當時我正在運行我的腳本,那麼肯定會失敗,所以如果我的上述腳本失敗,我可以通知,這樣我就可以確定發生了錯誤。

希望我的問題很清楚。

任何想法將不勝感激。

+0

@Levon,完成。現在好點了? – ferhan

+0

是的,我認爲這看起來更好,更具可讀性,不會威脅潛在的幫手:) – Levon

+0

是的..感謝您的意見。我會確保下次肯定。 :) – ferhan

回答

11

您可以檢查每個命令的退出狀態,freetx回答,但這是手動錯誤檢查而不是異常處理。在sh中獲得等效異常處理的標準方法是使用set -e啓動腳本。一旦任何執行的命令失敗(即以非零退出狀態退出),告知sh以非零狀態退出。

如果打算讓這樣的腳本中的某些命令(可能)失敗,那麼可以使用構造COMMAND || true,這將強制該表達式的零退出狀態。例如:

#!/bin/sh 

# if any of the following fails, the script fails 
set -e 
mkdir -p destdir/1/2 
mv foo destdir/1/2 
touch /done || true # allowed to fail 

的另一種方法,以確保出問題時在由cron調用的腳本是要堅持的printing nothing unless an error ocurred Unix的慣例,您會收到通知。成功的運行將在沒有通知的情況下通過,而不成功的運行將導致cron守護進程通過電子郵件通知您錯誤。請注意,本地郵件傳遞必須在您的系統上正確配置才能生效。

5

其習慣上每個unix命令行實用程序在成功時返回0,在失敗時返回非零。因此你可以使用$?模式來顯示最後的返回值並相應地處理事情。

例如:

> ls 
> file1 file2 
> echo $? 
> 0 
> ls file.no.exist 
> echo $? 
> 1 

因此,您可以以此爲基本的錯誤檢測,看看是否出現錯誤。因此,正常的做法是

some_command 
if [ $? -gt 0 ] 
then 
handle_error here 
fi 
+4

其實寫的那種習慣寫法是'if! some_command;然後......許多人似乎沒有意識到if的唯一目的是運行一個命令並檢查其退出代碼的成功或失敗狀態。 – tripleee

0

以及是否有其他腳本是在同一臺機器上,那麼你可以做其他腳本這個腳本p纖ep如果發現睡一會,並嘗試其他腳本日後複查過程不見了。

如果腳本是另一臺機器上,甚至當地的另一種方法是產生訪問遠程計算機上的臨時文件通過運行HTTP瀏覽器,其他腳本可以檢查狀態,即運行或完整

你也可以自動換行圍繞另一個腳本,以查找這些錯誤和電子郵件,你如果找到它,如果不是並將結果發送按正常;誰

go=0; 
function check_running() { 

     running=`pgrep -f your_script.sh|wc -l ` 
    if [ $running -gt 1 ]; then 
     echo "already running $0 -- instances found $running "; 
     go=1; 
} 

check_running; 
if [ $go -ge 1 ];then 
     execute your other script 
else 
    sleep 120; 
    check_running; 
fi