2013-05-11 129 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

相关问题