2013-05-11 108 views
2

我原來的問題是當超時時殺死一個進程&它的孩子。我發現GNU timeout是一個不錯的選擇。將命令結果分配給一個變量時Shell掛起

然而,在這個測試用例,事情就變得怪異:

假設我們有一個test1.sh這樣的:

#!/bin/sh 
# test1.sh 
output=`timeout 2 ./run.sh` 
echo $output 

run.sh這樣的:

#!/bin/sh 
# run.sh 
sleep 8s& 

直觀上我們應該預計test1.sh立即退出,因爲init將負責臨時t傻了sleep過程,然後run.sh將退出。

但是:

sh-4.2$ time ./test1.sh 

real 0m8.022s 
user 0m0.013s 
sys  0m0.003s 

如果我創建這個test2.sh

#!/bin/sh 
# test2.sh 
timeout 2 ./run.sh 
sh-4.2$ time ./test2.sh 

real 0m0.014s 
user 0m0.003s 
sys  0m0.007s 

所以,很明顯我們打命令替換過程中做錯事,但爲什麼呢?

回答

3

它可能是你的shell腳本有辦法 -

`timeout 2 ./run.sh` 

- 您使用命令替換,所以只要命令尚未執行完畢,置換能不能做到,因爲輸出不存在...這可能會解釋你看到的輸出。

試試這個,看看類似的結果....

echo "hello `sleep 2 &`" 

另一個有趣的劇本 -

$ cat y.sh 
echo "hi" 
sleep 2 & 
echo "bye" 
sleep 2 & 

使用

echo "hello `sh y.sh`" 

$time sh y.sh 
hi 
bye 

real 0m0.006s 
user 0m0.000s 
sys  0m0.004s 

$time echo "hello `sh y.sh`" 
hello hi 
bye 

real 0m2.008s 
user 0m0.004s 
sys  0m0.000s 

This page運行詳細解釋關於關係後臺進程和文件描述符之間的髖關節。 Basicly:

背景(最好:叉)進程繼承文件描述符, 和反引號運行命令的方法收集其標準輸出,直到 標準輸出關閉

+0

是的,你的榜樣澄清事情做得更好!但我認爲,在我的例子中,'run.sh'應該*退出*,因爲它的原始子節點被'init'接管了嗎? – sleepsort 2013-05-11 03:07:07

+0

是的,它會被'init'接管,但是它的執行還沒有結束.....所以輸出還沒有準備好還有待替換.... – Bill 2013-05-11 03:09:14

+0

請看我的第二個例子來驗證這個.. ..'y.sh'應該很快退出,但由於在後臺運行,'echo'命令需要超過'2secs'來完成...有趣的東西:) – Bill 2013-05-11 03:11:14