2012-01-19 307 views
0

我正在編寫一個例程,它將識別進程是否停止運行,並在目標進程結束後執行某些操作。shell while循環不停止

我想出了這個代碼(爲我將來的代碼測試):

#!/bin/bash 
value="aaa" 
ls | grep $value 
while [ $? = 0 ]; 
    do 
    sleep 5 
    ls | grep $value 
    echo $? 
done; 
echo DONE 

我的問題是,由於某種原因,該循環永遠不會停止,呼應1我刪除文件「AAA」之後。

0 
0 >>> I delete the file at that point (in another terminal) 
1 
1 
1 
1 
. 
. 
    . 

我期望的輸出被「DONE」只要我刪除文件...

什麼問題?

SOLUTION:

#!/bin/bash 
value="aaa" 
ls | grep $value 
while [ $? = 0 ]; 
    do 
    sleep 5 
    ls | grep $value 
done; 
echo DONE 

回答

6

$?的值很容易改變。在當前版本的代碼,這條線:

echo $? 

打印前一個命令(grep)的狀態 - 但然後設置$?爲0,echo命令的狀態。

保存的$?另一個變量,一個價值不會被打一頓在下一次執行命令:如果ls | grep aaa用來檢查一個名爲aaa文件是否存在,這

#!/bin/bash 
value="aaa" 
ls | grep $value 
status=$? 
while [ $status = 0 ]; 
    do 
    sleep 5 
    ls | grep $value 
    status=$? 
    echo $status 
done; 
echo DONE 

while [ ! -f aaa ] ; ... 

是一個更乾淨的方式來做到這一點。

+0

謝謝,這僅僅是一個例子。我的最終命令是: ps -ef | grep「mysqldump」| grep -v「grep mysqldump」 while [$? = 0]; \t do \t sleep 1200 \t ps -ef | grep「mysqldump」| grep -v「grep mysqldump」; 完成; tar cvzf [dumpdir] [files] rm [files] – Rgonomike

+2

@Rgonomike:你可以這樣寫:「while ps -ef | ... | grep mysqldump; do sleep 1200; done」。這將簡化代碼。 (雖然解析ps的方法是錯誤的,但你真正想要的是讓mysqldump的父節點執行後續處理,因爲當mysqldump退出時它會發出警報。) –

2

$?是最後一個命令的返回碼,在這種情況下,你sleep

+0

我按照你的建議編輯了腳本(只是移動了我的睡眠命令)。它仍然不起作用,雖然...相同的結果。 還有其他建議嗎? – Rgonomike

+0

現在'$?'是'echo'命令的結果。 –

+0

確實!好的問題解決了。 謝謝。 – Rgonomike

1

您可以重寫環路更簡單的方式是這樣的:

while [ -f aaa ]; do 
    sleep 5; 
    echo "sleeping..."; 
done 
1

你不應該複製的命令進行測試。你總是可以寫:的

 
cmd 
while [ $? = 0 ]; do ...; cmd; done 

 
while cmd; do ...; done 

,而不是在你的情況,你的評價是正在測試的命令解析PS的輸出不在話下。雖然有很好的論點,你不應該這樣做,並且後續處理應該由你正在等待的命令的父母來完成,但我們現在將忽略這個問題。你可以簡單的寫:

 
while ps -ef | grep -v "grep mysqldump" | 
    grep mysqldump > /dev/null; do sleep 1200; done 

請注意,我改變了你管的順序,因爲grep的-v將返回true,如果它 匹配任何內容。在這種情況下,我認爲這是沒有必要的,但我相信更可讀的是 。我也放棄了輸出來清理一些東西。

+1

有一個技巧可以避免'grep ... | grep -v grep':'grep'[m] ysqldump'' –

0

推測你的目標是等到包含字符串$value的文件名存在於本地目錄中,而不一定是單個文件名。

嘗試:

#!/bin/bash 
value="aaa" 
while ! ls *$value*; do 
    sleep 5 
done 
echo DONE 

你原來的代碼失敗,因爲$?充滿echo命令一旦在第一每次迭代的返回碼。

順便說一句,如果你打算在未來使用ps而不是ls,除非你很聰明,否則你會選擇自己的grep。使用ps -ef | grep [m]ysqlplus