michel-slm
michel-slm

Reputation: 9756

How to pipe a long-lasting command until either the first match or timing out?

I have a remote syslog tailer for a device that, if a condition is present, would contain a particular string every about 15 seconds or so. It can be detected by running it as such:

(timeout 20 remote-logger 2>&1) | grep -m 1 KEY

(Using a higher timeout value to compensate for potential jitters)

Is there a way to short-circuit this if the KEY string is found earlier?

Upvotes: 0

Views: 119

Answers (1)

Charles Duffy
Charles Duffy

Reputation: 295443

In bash 4.4 with a GNU toolchain, you can do the following:

exec 3< <(stdbuf -oL remote-logger | grep --line-buffered -m 1 KEY); pid=$!
read -t 20 -r key <&3
kill "$pid"

Prior to 4.4, $! won't capture the PID of a process substitution, so you won't be able to execute a kill -- but the other parts should work.


Incidentally, you can also do the filtering natively in shell (with lower throughput, but lesser pipeline startup costs):

result=
while IFS= read -r line; do
  case $line in
    *KEY*) result=$line;;
    *) continue;;
  esac
done < <(timeout 20 remote-logger)

Upvotes: 2

Related Questions