如何在标准错误中看到特定字符串时,如何终止进程?

9 bash grep stderr

我要说,我需要开始一个过程foo.我想看到stdout/stderr正常,但是grep字符串的stderr bar.一旦bar发现stderr foo应该被杀死.

这可能吗?

Tom*_*son 5

我最初写了一个方法来做这个涉及流调配,但它不是很好.一些评论与该版本有关.如果你好奇,请检查历史.

这是一种方法:

(PIDFILE=$(mktemp /tmp/foo.XXXXXX) && trap "rm $PIDFILE" 0 \
   && { foo \
           2> >(tee >(grep -q bar && kill $(cat $PIDFILE)) >&2) \
        & PID=$! && echo $PID >$PIDFILE ; wait $PID || true; })
Run Code Online (Sandbox Code Playgroud)

好老式的噩梦燃料.这里发生了什么事?

  1. 最外面的括号将整个东西放在子壳中; 为了hygeine的目的,这限制了变量的范围
  2. 我们创建一个临时文件,使用与GNU和BSD一起使用的语法mktemp,然后调用它PIDFILE
  3. 我们设置了一个catch-all出口陷阱(在最外面的子shell退出时运行)以删除名为的文件PIDFILE,同样用于hygeine
  4. 我们跑foo; 这是在复合语句中完成的,以便&绑定到foo整个前面的管道而不是绑定到整个前面的管道
  5. 我们将foo标准错误重定向到一个等待bar出现然后杀死的进程替换foo(后来更多)
  6. 我们将fooPID 捕获到变量中,将其写入命名的文件PIDFILE,然后等待它,以便整个命令在foo退出之前等待退出; 该|| true丢弃的错误退出状态foo当这种情况发生.

进程替换中的代码如下:

  1. 首先,tee输入(foo标准错误),将tee标准输出重定向到标准错误,因此foo标准错误确实出现标准错误
  2. 将输入的副本发送到另一个进程替换的文件(进程替换的进程替换)
  3. 在更深层次的过程替换中,首先grep -q在输入上运行,该输入查找指定的模式,并在找到它时立即退出(或者当它到达流的末尾时),而不打印任何内容,之后(如果它找到了字符串并退出成功)shell继续...
  4. kill在其命名的文件中捕获PID的进程PIDFILE,即foo


小智 5

汤姆安德森的答案非常好,但kill $(cat $PIDFILE)只有在我自己的系统foo上或通过Ctrl-C终止时才会发生.以下解决方案适合我

while read g
do
  if [[ $g =~ bar ]]
  then
    kill $!
  fi
done < <(
  exec foo 2> >(tee /dev/tty)
)
Run Code Online (Sandbox Code Playgroud)