【发布时间】:2016-09-05 15:50:20
【问题描述】:
我正在尝试制作一个我认为是简单的 bash 脚本,它定期轮询远程数据库并将以下元素记录到日志文件中,其中只有最后两个元素是来自 sql 的行元素-查询:
Readable timestamp, timestamp, string, Request Duration
示例结果应如下所示:
Mon Sep 5 13:28:30 CEST 2016,1473074940127,text content, 4
Mon Sep 5 13:28:40 CEST 2016,1473074940127,text content, 3
Mon Sep 5 13:28:50 CEST 2016,1473074940127,text content, 2
此脚本的目的是主动监控和记录从本地环境到远程数据库的响应时间,以便我们可以在测试时对应本地应用程序中的错误,以及最终的数据库连接问题或类似问题。出于这个原因,我们希望脚本也输出任何最终的错误消息。这些格式并不重要,但我们希望看到标准输出是“舒适”的单行。
我为这个场合编写了以下非常简单的脚本,但它有一些怪癖,无论我如何调整它似乎都无法消除:
sleep_duration=10
while true; do
SECONDS=0
timestamp="$(date),"
echo -n $timestamp >> $LOG_PATH
sqlplus -s $database << EOF >> $LOG_PATH
whenever sqlerror exit sql.sqlcode
set echo off
set heading off
set linesize 1000
set pagesize 0
set numformat 9999999999999
set colsep ,
set null null
SELECT COLUMN1, COLUMN2 FROM TABLE1;
exit;
EOF
echo ', '$SECONDS >> $LOG_PATH
sleep $sleep_duration
done
我们发送到数据库的查询总是返回恰好包含两个元素的一行,并且这两个元素(INTEGER、VARCHAR2)总是具有相同的固定宽度。如果我们的应用程序中的某些内容在本地中断,则它们都可以为 null。
我知道 SPOOL 和 TIMING 命令的存在,但已经测试并选择不使用这两个命令。假脱机查询不会向日志文件输出任何最终的意外错误,至少不会在没有错误终端输出的情况下进行欺骗,所以我首先使用了管道解决方案。看起来更简单。在数据库停机的情况下,TIMING 似乎无法正确显示查询经过的时间,所以我采用了 SECONDS 方法。我知道这对于包含的所有 sqlplus 开销来说并不精确,但无论如何我们对精确的指标不感兴趣,我们通常只对查看该过程是否需要不到一秒或几分钟感兴趣。毫秒基本上是无关紧要的。
然而,这有一个大问题,因为日志最终看起来像这样:
Mon Sep 5 14:50:47 CEST 2016, 1473079873483,text output
, 0
Mon Sep 5 14:50:57 CEST 2016, 1473079883483,text output
, 0
Mon Sep 5 14:51:07 CEST 2016, 1473079893489,text output
, 0
我希望set pagesize 0 从结果中删除所有此类尾随换行符,但无论如何,每次查询后似乎都有两个换行符,而且无论我尝试什么,我似乎都无法摆脱它。假脱机查询给出了相同的结果。
我考虑改为在 sqlplus-session 内循环,但由于脚本必须或多或少地永久运行,我担心这会永久保留一个连接槽,用于其他功能无意义的目的,这是不可取的。根据需要打开和关闭它似乎更明智。我根本没有测试过这种方法,主要是因为这个原因。
我希望避免对日志进行后处理,因为我不知道其中可能会弹出什么样的错误条目,所以稍后美化它就像是不必要的正则表达式噩梦。
是否有人对如何使输出在单行上整齐排列,没有不必要的换行和空格,同时确保不丢失任何最终错误有任何建议?
【问题讨论】:
-
字符串列的数据类型是什么 - 你说的是 varchar2 但真的不是 char 或 clob;它有多大;字符串值是否有尾随空格或嵌入的换行符?
-
字符串值是一个普通的 URL,字段声明为 varchar2(250),内容的实际长度为空,或大约 560 个字符长。没有空格或换行符,嵌入的,前导的或尾随的 - 尽管我会三重检查是否没有尾随换行符只是为了验证。应该没有,但是 URL 是部分生成的,所以我不是 100% 确定没有检查。
-
可以确认,文本字段中根本没有空格或换行符,并且字符串总是正好 36 个字符宽。 (如果发生爆炸,则为 null)