从命令输出中捕获错误,在文本处理管道中检测它们

问题描述 投票:0回答:1

bash (RHEL 7) 脚本的以下部分在 Ingres sql 命令上调用 SELECT SQL,如果查询成功,则以文本格式返回结果,其中包含查询本身的日志,后跟由管道分隔的结果。有一个管道可以捕获实际的表格输出并保存为 CSV、格式化日期等。

sql $HBDB <<_END_ | grep '^|' | sed -E 's/^\|//; s/\|$//; s/ *\| */","/g; s/^ *| *$//g; s/^/"/; s/$/"/; s/#//g; s;([0-9]{2})\.([0-9]{2})\.([0-9]{4});\1/\2/\3;g' > $OUTFILE1
    set autocommit on;
    \p\g
    set lockmode session where readlock = nolock;
    \p\g
    select * from table
    \p\g
 _END_

但是,我们运行的 SQL 中偶尔会出现拼写错误/错误,导致输出文件为空。这是令人沮丧的,因为错误的实际原因与错误代码一起包含在输出中,但这一切都被管道删除了。所以我们必须手动从脚本中删除管道,然后重试,以查看错误的详细信息。

我想尝试检查管道中是否存在错误代码(由出现在行开头的“E_”表示),如果是,则将整个输出(不仅仅是该行)发送到存储的文件路径在 $ERRLOG 变量中(因此运行后,我们可以轻松检查错误日志)。但是,我正在努力让它工作,以下代码不起作用,ERROLOG 文件是空的

 sql $HBDB <<_END_ | tee >(grep '^E_' && cat > $ERRLOG && exit 1) | grep '^|' | sed -E 's/^\|//; s/\|$//; s/ *\| */","/g; s/^ *| *$//g; s/^/"/; s/$/"/; s/#//g; s;([0-9]{2})\.([0-9]{2})\.([0-9]{4});\1/\2/\3;g' > $OUTFILE1
    set autocommit on;
    \p\g
    set lockmode session where readlock = nolock;
    \p\g
       /* errant query */
    selet * from table_which_does_not_exist
    \p\g
 _END_

我认为这会在任何行的开头检查“E_”文本的输出,如果是这样,则将整个输出发送到 ERRLOG 并退出脚本,但这并没有发生,所有输出都是空的,并且 exit 1 命令是没有被调用。

我想在管道中执行此操作的原因是因为我们有大量调用 sql 命令的脚本,并将输出保存到 CSV,并且我想要尽可能少的代码。

bash unix error-handling
1个回答
0
投票

我不会尝试将这一切作为管道在一行中完成,只需使用临时文件保持简单即可,例如未经测试:

tmp=$(mktemp) || exit
trap 'rm -f "$tmp"; exit' EXIT

sql "$HBDB" <<_END_ > "$tmp"; rslt="$?"
    set autocommit on;
    \p\g
    set lockmode session where readlock = nolock;
    \p\g
       /* errant query */
    selet * from table_which_does_not_exist
    \p\g
_END_

if (( rslt == 0 )); then
    grep '^|' "$tmp" | sed -E 's/^\|//; s/\|$//; s/ *\| */","/g; s/^ *| *$//g; s/^/"/; s/$/"/; s/#//g; s;([0-9]{2})\.([0-9]{2})\.([0-9]{4});\1/\2/\3;g' > "$OUTFILE1"
else
    cat "$tmp" >> "$ERRLOG"
fi
© www.soinside.com 2019 - 2024. All rights reserved.