如何有条件地在管道中执行/终止命令

时间:2019-02-07 03:01:11

标签: bash shell

我正在处理一个脚本,该脚本需要检测程序中对FFMPEG的首次调用,并从那时开始运行脚本。

核心代码如下:

strace -f -etrace=execve <program> 2>&1 | grep <some_pattern> | <run_some_script>

所需的行为是,当第一个 grep 结果出来时,脚本应启动。并且,如果<program>终止之前没有匹配的内容,则应忽略该脚本。

主要问题是如何根据grep的输出有条件地执行脚本,以及在程序终止后如何终止脚本。

我认为可以使用 read 解决第一个问题,因为使用 grep 文本作为信号,因此其内容无关紧要:

... | read -N 1 && <run_some_script>

第二个可以使用折断管道机制解决:

<run_some_script> > >(...)

但是我不知道如何使它们一起工作。还是有更好的解决方案?

2 个答案:

答案 0 :(得分:2)

您可以要求grep仅匹配一次模式,然后返回并使其返回成功错误代码。将这些放在一起(如果有条件的话)

if strace -f -etrace=execve <program> 2>&1 | grep -q <some_pattern>; then
    echo 'run a program'
fi

-q标志用于禁止显示由grep命令返回的通常标准输出内容,正如您提到的那样,您只想使用grep结果执行操作而不使用结果。

或者您可能需要使用coproc运行命令以在后台运行,并检查产生的输出的每一行。只需为要运行的命令编写包装器,如下所示。 单个命令不需要该功能,但是对于多个命令,该功能将更为重要。

wrapper() { strace -f -etrace=execve <program> 2>&1 ; }

使用coproc类似于在后台运行命令,但是提供了一种捕获命令运行输出的简单方法

coproc outputfd { wrapper; }

现在,通过读取wrapper提供的文件描述符,观察coproc内部运行的命令的输出。下面的代码将监视输出,并在pattern的第一个匹配项上启动它,以启动运行该命令的后台作业,并将进程ID存储在pid中。

flag=1
while IFS= read -r -u "${outputfd[0]}" output; do
    if [[ $output == *"pattern"* && $flag -eq 1 ]]; then
        flag=0
        command_to_run & pid=$!
    fi
done

当循环终止时,这意味着由coproc开始的后台作业已完成。到那时,杀死脚本开始。为了安全起见,请检查其是否还活着并杀死

kill "$pid" >/dev/null 2>&1

答案 1 :(得分:0)

使用ifne util

strace -f -etrace=execve <program> 2>&1 | 
grep <some_pattern> | ifne <some_script>