2010-10-28 56 views
6

我有以下bash脚本:bash脚本不会立即退出时`exit`被称为

tail -F -n0 /private/var/log/system.log | while read line 
do 
    if [ ! `echo $line | grep -c 'launchd'` -eq 0 ]; then 
     echo 'launchd message' 
     exit 0 
    fi 
done 

出于某种原因,这是呼应launchd message,等待了整整5秒,然后退出

为什么会发生这种情况,如何在响应后立即退出launchd message

回答

9

由于您正在使用管道,while循环正在一个子shell中运行。改为在主外壳中运行它。

#!/bin/bash 

while ... 
do 
    ... 
done < <(tail ...) 
+0

我在做线得到一个语法错误... – Chetan 2010-10-29 01:48:45

+0

啊,那是因为我是用/ bin/sh的,愚蠢的我。 – Chetan 2010-10-29 02:00:42

+0

调用bash作为sh会禁用某些功能,包括进程替换。 – 2010-10-29 02:04:43

3

正如Ignacio所示,您的tail | while创建了一个子外壳。延迟是因为它在等待下一行被写入日志文件之前一切都关闭。

您可以立即加入这一行你exit命令之前,如果你不想使用进程替换:

kill -SIGPIPE $$ 

不幸的是,我不知道有什么办法来控制使用这种方法的退出代码。它将是141 + 128 + 13(信号编号SIGPIPE)。

如果你想让一个守护进程的启动依赖另一个守护进程启动,那么可能有更好的方法。顺便说一句,如果你真的写了一个Bash脚本(你必须使用<()进程替代),你可以这样编写ifif [[ $line == *launchd* ]]

2

您也可以用告诉退出代码退出子shell,然后测试“$?”的值。让你在寻找同样的效果:

tail -F -n0 /private/var/log/system.log | while read line 
do 
    if [ ! `echo $line | grep -c 'launchd'` -eq 0 ]; then 
     echo 'launchd message' 
     exit 10 
    fi 
done 
if [ $? -eq 10 ]; then exit 0; fi