I have a script (eg. compute.sh) that does something on my Ubuntu 16.04 and may end with error, let's say:
[compute.sh]
#!/bin/bash
...
MISCELLANEOUS OPERATIONS
...
[if error occours]
echo "Error 55a" >&2;
exit 1;
...
echo "Execution ok";
exit 0;
and another script that handles errors (eg. error_handler.sh)
[error_handler.sh]
error=$(cat)
for i in "$@"
do
case $i in
-u=*|--user=*)
username="${i#*=}"
shift
;;
-t=*|--task=*)
task="${i#*=}"
shift
;;
esac
done
...
SENDS ERROR REPORTING THROUGH AN API LISTENING REMOTELY
...
I'd like to execute compute.sh, redirecting its stderr to error_handler.sh in order to notify my API system the error occourred
if I try this test:
user@ubuntu: echo "test message" | ./error_handler.sh --user=dude --task="simple task"
my error_handler.sh script takes the string "test message" and correctly handles it
how can I redirect only the stderr output to my error_handler.sh script?
EDIT: as sometimes compute.sh may fail without an error message (just by doing exit 1;) I'm not sure if error=$(cat) it's the right way to catch the error message in error_handler.sh. Any other option?
EDIT2: the task may be executed in a crontab, so I need to do all in the same command
The simplest thing to do is create a named pipe to act as the buffer between the two.
mkfifo errors # "errors" is an arbitrary file name
compute.sh 2> errors & # Run in the background
error_handler.sh < errors
As one line:
mkfifo errors; compute.sh 2> errors & error_handler.sh
Now the two processes run concurrently, and error_handler.sh
can read from errors
as compute.sh
writes to it. The buffer is of bounded size, so compute.sh
will automatically block if it gets full. Once error_handler.sh
consumes some input, compute.sh
will automatically resume. As long as errors aren't produced too quickly (i.e., faster than error_handler.sh
can process them), compute.sh
will run as if the buffer were unbounded.
If the buffer is ever emptied, error_handler.sh
will block until either more input is available, or until compute.sh
closes its end of the pipe by exiting.
Regular pipeline syntax foo | bar
creates an anonymous pipe (or unnamed pipe), and it is just a shortcut for
mkfifo tmp
foo > tmp &
bar < tmp
but limits you to connecting standard output of one command to standard input of another. Using other file descriptors requires contorted redirections. Using named pipes is slightly longer to type, but can be much clearer to read.