在 Linux 输出中的关键字后终止命令

Terminate command after keyword in output in Linux

如果命令输出中显示某个关键字,我想发送一个 SIGKILL。例如,如果发出以下命令:

ubuntu@ip-172-31-24-250:~$ ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=109 time=0.687 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=109 time=0.704 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=109 time=0.711 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=109 time=0.809 ms
64 bytes from 8.8.8.8: icmp_seq=5 ttl=109 time=0.727 ms
64 bytes from 8.8.8.8: icmp_seq=6 ttl=109 time=0.835 ms
^C

看到输出后 "icmp_seq=6" 我希望命令自动停止。我知道 ping 8.8.8.8 -c 6 会有相同的结果,但这只是为了举例。

您可以这样做的一种方法是将命令输出重定向到一个文件,然后为您想要的特定字符串设置一个循环到 grep 文件。如果 grep 成功,则结束循环并终止进程。 ping 的脚本可能如下所示:

这有一个错误

ping www.google.com > output 2> error &

while [ true ]; do
    grep "icmp_seq=6" output
    
    if [ $? -eq 0 ]; then
        break
    fi
done

echo "sequence found, killing program"

pid=`pgrep ping` # get the PID of ping so we can kill it
kill -9 ${pid}

更新: 我刚想到这个脚本有一个缺点,如果搜索文本永远不会出现,它将 运行 无限(并且它实际上会继续到 运行 无限甚至在候选程序终止后,或者程序在启动时立即死亡)。因此,这是一个改进的脚本,可以解决所有这些问题:

ping www.google.com > output 2> error & # the & makes the command a background process so execution of other commands isn't blocked

pid=`pgrep ping`

while [ ! -z ${pid} ]; do # check if pid contains anything - if so, the ping command is still running
    grep "icmp_seq=6" output
    
    if [ $? -eq 0 ]; then
        echo "sequence found, killing program"
        kill -9 ${pid}
        exit 0
    fi

    pid=`pgrep ping`
done

echo "Sequence not found"

优化更新:因为我对这些东西有强迫症,如果输出很多,这个脚本可能会陷入困境,因为 grep 必须筛选所有它的。因此,我的优化建议是使用 tail -1 output 然后将输出通过管道传输到 grep,结果是这个脚本:

ping www.google.com > output 2> error & # the & makes the command a background process so execution of other commands isn't blocked

pid=`pgrep ping`

while [ ! -z ${pid} ]; do # check if pid contains anything - if so, the ping command is still running
    tail -1 output | grep "icmp_seq=6"
    
    if [ $? -eq 0 ]; then
        echo "sequence found, killing program"
        kill -9 ${pid}
        exit 0
    fi

    pid=`pgrep ping`
done

echo "Sequence not found"

请您尝试以下操作:

#!/bin/bash

ping 8.8.8.8 | while IFS= read -r line; do
    echo "$line"
    [[ $line =~ icmp_seq=6 ]] && kill -9 $(pidof ping)
done