2013-08-23 22 views
0

我用下面的腳本通過超時殺進程的過程:怎樣一個人準確地殺死在bash

# $1 - name of program and its command line 

#launch program and remember PID 
eval "$1" & 
PID=$! 

echo "Program '"$1"' started, PID="$PID 

i=1 
while [ $i -le 300 ] 
do 
ps -p $PID >> /dev/null 
if [ $? -ne 0 ] 
    then 
    wait $PID 
    exit $? #success, return rc of program 
    fi 

i=$(($i+1)) 
echo "waiting 1 second..." 
sleep 1 
done 

#program does not want to exit itself, kill it 
echo "killing program..." 
kill $PID 
exit 1 #failed 

到目前爲止,它已經工作出色,但今天,我已經注意到了一堆「掛」在htop進程,所以我已經檢查出來,事實證明,在這種情況下,$PID不是程序進程的ID,而是腳本本身的ID,並且所有時間我檢查,該程序的ID是$PID+1。現在的問題是,我是正確的假設,它永遠是$PID+1,我不會用的東西代替kill $PIDkill $PID $($PID+1)殺死一些重要的東西

編輯:$1可能有幾個urguments,像./bzip2 -ds sample3.bz2 -k

+0

沒有,PID可以是任何東西。這取決於系統上運行的內容。 – choroba

+0

您可以使用'pidof '來返回進程的PID。在這種情況下,將會是'$ 1'。 –

+0

@SakthiKumar可能是exacly我需要什麼,謝謝,我會測試它,並很快回復 – Shf

回答

3

您可以用下面的變化只是解決問題:

來源:

eval "$1" & 

要:

eval "$1 &" 

的原因是this answer解釋。

1

平原有什麼問題

(eval "$1") & 
sleep 300 
kill %1 
+0

我需要有返回代碼的進程,如果它事先完成,不等待300秒,因爲這個腳本啓動很多次 – Shf

+0

'(sleep 300; kill $ PID)&wait $ PID' – chepner

+0

感謝您的好回覆,但對於我評估「$ 1 &「固定問題 – Shf

2

我剛開始寫這個功能的腳本。我打算叫它「超時」,但在我打開一個空白文件之前,我檢查了是否已經有一個同名的命令。有...

timeout

編輯

如果需要 「1」 特別是作爲失敗返回值...

timeout 1 nano -w; `if [[ $? == 124 ]] ; then exit 1 ; fi ; exit $?` 
+1

我知道這個命令,但是fom man'如果命令超時,那麼退出時狀態爲124'不適合。有大量的遺留腳本,其中「1」被期望作爲掛起程序的返回碼,所以我被捆綁在這裏 – Shf

+0

@Shf如果命令尚未完成,它將不會有輸出。你想要什麼? – jozxyqk

+0

timeout超時後會返回124,但是在一大堆腳本中1期望返回這種情況 – Shf

1

你backgrounding eval,不它運行的命令,並且eval是一個內置的shell,所以你正在分配一個新的shell;這就是爲什麼(我認爲)$!是當前shell的PID。

一個簡單的解決方案是避免使用eval(爲此以及對安全性的常見擔憂)。

$1 "[email protected]" & 
PID=$! 

誠然,這並不讓你通過一個任意bash命令行(管道,& &清單等)到你的腳本,但您的使用情況下可能不需要支持這種泛化。你通常會傳遞什麼命令?

+0

需要eval,因爲'<' and '>'經常使用,比如'./cc_dry2 < dhryinput > results',沒有'eval' bash是混淆的 – Shf

0

而且,這裏是一些重構你的代碼,也許你會從中學到東西:

#launch program and remember PID 
eval "$1" & 
PID=$! 

echo "Program '$1' started, PID=$PID" # you can safely use single quotes inside double quotes, your variables are going to work in " " as well! 

i=1 
while ((i <= 300)) # use (()) for math operations! 
do 
    ps -p "$PID" >> /dev/null # it is a good rule to quote every variable, even if you're pretty sure that it doesn't contain spaces 
    if [[ $? != 0 ]]; then # Try to use [[ ]] instead of [. It is modern bash syntax 
     wait "$PID" 
     exit "$?" #success, return rc of program 
    fi 
    ((i++)) 
    echo "waiting 1 second..." 
    sleep 1 
done 

#program does not want to exit itself, kill it 
echo "killing program..." 
kill "$PID" 
exit 1 #failed