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,并且我想要尽可能少的代码。
我不会尝试将这一切作为管道在一行中完成,只需使用临时文件保持简单即可,例如未经测试:
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