用另一个脚本处理 stderr

handle stderr with another script

我有一个脚本(例如 compute.sh)在我的 Ubuntu 16.04 上执行某些操作并且可能以错误结束,比方说:

[compute.sh]

#!/bin/bash

...

MISCELLANEOUS OPERATIONS

...

[if error occours]
echo "Error 55a" >&2;
exit 1;

...

echo "Execution ok";
exit 0;

和另一个处理错误的脚本(例如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

...

我想执行 compute.sh,将其 stderr 重定向到 error_handler.sh 以便通知我的 API 系统发生了错误

如果我尝试这个测试:

user@ubuntu: echo "test message" | ./error_handler.sh --user=dude --task="simple task"

我的 error_handler.sh 脚本接受字符串 "test message" 并正确处理它

如何仅将 stderr 输出重定向到我的 error_handler.sh 脚本?

编辑:有时 compute.sh 可能会在没有错误消息的情况下失败(只需执行 exit 1;)我不确定 error=$(cat) 是否是捕获错误消息的正确方法error_handler.sh。还有其他选择吗?

EDIT2:任务可能在 crontab 中执行,所以我需要在同一个命令中执行所有操作

最简单的做法是创建一个命名管道作为两者之间的缓冲区。

mkfifo errors           # "errors" is an arbitrary file name
compute.sh 2> errors &  # Run in the background
error_handler.sh < errors

作为一行:

mkfifo errors; compute.sh 2> errors & error_handler.sh 

现在两个进程 运行 并发,并且 error_handler.sh 可以从 errors 读取,而 compute.sh 可以写入它。缓冲区大小有限,所以 compute.sh 如果满了会自动阻塞。一旦 error_handler.sh 消耗了一些输入,compute.sh 将自动恢复。只要错误不会产生得太快(即比 error_handler.sh 处理它们的速度更快),compute.sh 将 运行 就好像缓冲区是无限的。

如果缓冲区被清空,error_handler.sh 将阻塞直到有更多输入可用,或者直到 compute.sh 通过退出关闭其管道末端。


常规管道语法foo | bar创建匿名管道(或未命名管道),它只是

的快捷方式
mkfifo tmp
foo > tmp &
bar < tmp

但限制您将一个命令的标准输出连接到另一个命令的标准输入。使用其他文件描述符需要扭曲的重定向。使用命名管道的输入时间稍长,但阅读起来更清晰。