I want to send a SIGKILL if a certain keyword is shown in the output of the command. Eg, if issue the following command:
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
After seeing the output "icmp_seq=6" I'd like the command to automatically halt. I know that ping 8.8.8.8 -c 6 will have the same results, but it's just for the example.
CodePudding user response:
One way you can do it is redirect the command output to a file, then set up a loop to grep
the file for the particular string you want. If the grep
succeeds, then end the loop and kill the process. Such a script for ping
might look like this:
THIS HAS A BUG IN IT
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}
Update: It just occurred to me that this script has a downfall in that it will run infinitely if the search text never appears (and it will actually continue to run infinitely even after the candidate program terminates, or the program dies immediately on startup). Thus, here's an improved script that accounts for all of that:
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"
Optimization update: Because I'm OCD about this stuff, this script can get bogged down if there's a lot of output because grep
has to sift through all of it. Thus, my optimization suggestion would be to use tail -1 output
and then pipe the output to grep
, resulting in this script:
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"
CodePudding user response:
Would you please try the following:
#!/bin/bash
ping 8.8.8.8 | while IFS= read -r line; do
echo "$line"
[[ $line =~ icmp_seq=6 ]] && kill -9 $(pidof ping)
done