From OP's comments it sounds like all mycommand output is going to stderr ... maybe. OP has also clarified that mycommand is writing directly to the log file.
I'm going to assume we don't know, for sure, if output is going to stdout, stderr or a mix.
For demo purposes I'll use the following:
% cat mycommand
#!/bin/zsh
for str in "starting ..." "running ..." "ERROR: had a problem" "stopping"
do
if [[ "${str}" =~ ERROR: ]]
then
echo "${str}" >&2 # remove ">&2" to write to stdout
else
echo "${str}" # append ">&2" to write to stderr
fi
sleep 2
done
One approach using redirection to split the output (to monitor and follow-on processing) and grep to find lines we wish to feed to espeak:
% ./mycommand 1> >(tee /dev/tty | grep --line-buffered '^ERROR:' | espeak) 2>&1
starting ...
running ...
ERROR: had a problem # espeak output heard on speakers
stopping
NOTES:
- regardless of modifying
mycommand to send output to stdout, stderr or a mix of stdout/stderr ...
- in my system I hear
ERROR <pause> had a problem over my speakers as the line ERROR: had a problem was printed to the terminal
tee /dev/tty - insures all data coming in on stdout is copied to the terminal before being piped to grep
2>&1 - insures all data coming in on stderr is redirected to stdout (which means stderr is also routed through the tee /dev/tty | grep ... | espeak pipeline)
grep is used to extract just the lines we wish to pass to espeak; if looking for multiple strings you'll likely need to enable extended regex support (eg, grep -E ...)
--line-buffered is a GNU grep extension that insures we hear the espeak output at the same time as we see the ERROR: line
- OP can install
espeak via sudo apt install espeak
- OP can replace
espeak with whatever sound producing program they wish
This solution (above) will speak the entire line when said line contains the string ^ERROR:.
If OP wishes to only speak the single word ERROR whenever the string ERROR is seen anywhere in the line:
./mycommand 1> >(tee /dev/tty | grep -o --line-buffered 'ERROR' | espeak) 2>&1
Allowing for case insensitive matching on the string ERROR anywhere in the line while only speaking the single word error:
./mycommand 1> >(tee /dev/tty | grep -oi --line-buffered 'ERROR' | espeak) 2>&1
Speaking just the word error or warning when there's a case insensitive match on the strings ERROR and/or Warning in the line:
./mycommand 1> >(tee /dev/tty | grep -oi -E --line-buffered '(ERROR|WARNING)' | espeak) 2>&1
Modifying mycommand to output the following lines:
starting ...
WARNING: had a warning
running ...
ERROR: had a problem
stopping
error warning
The following sends Danger Will Robinson to the speaker (max of once per input line) whenever there's a case-insensitive match on the strings ERROR or warning:
./mycommand 1> >(tee /dev/tty | sed -unE '/(ERROR|WARNING)/I s/.*/Danger Will Robinson/p' | espeak) 2>&1
mycommandwrite directly to the log file or are you (re)directing the output frommycommandto the log (eg,mycommand | tee -a logfile)? doesmycommandwrite the error message to stdout or stderr?