将命令结果分配给一个变量时Shell挂起
问题描述:
我原来的问题是当超时时杀死一个进程&它的孩子。我发现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
所以,很明显我们打命令替换过程中做错事,但为什么呢?
答
它可能是你的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:
背景(最好:叉)进程继承文件描述符, 和反引号运行命令的方法收集其标准输出,直到 标准输出关闭
是的,你的榜样澄清事情做得更好!但我认为,在我的例子中,'run.sh'应该*退出*,因为它的原始子节点被'init'接管了吗? – sleepsort 2013-05-11 03:07:07
是的,它会被'init'接管,但是它的执行还没有结束.....所以输出还没有准备好还有待替换.... – Bill 2013-05-11 03:09:14
请看我的第二个例子来验证这个.. ..'y.sh'应该很快退出,但由于在后台运行,'echo'命令需要超过'2secs'来完成...有趣的东西:) – Bill 2013-05-11 03:11:14