无法从 BASH 脚本中建立 Oracle SQL 会话

Posted

技术标签:

【中文标题】无法从 BASH 脚本中建立 Oracle SQL 会话【英文标题】:Not able to establish Oracle SQL session from within a BASH script 【发布时间】:2017-02-21 20:49:21 【问题描述】:
#!/bin/bash
#Oracle DB Info for NEXT
HOST="1.2.3.4"
PORT="5678"
SERVICE="MYDB"
DB_USER=$(whoami)
DB_PASS=$(base64 -d ~/.passwd)
DB_SCHEMA="my_db"

#Section for all of our functions.
function SQLConnection()
sqlplus "$DB_USER"/"$DB_PASS"@"$HOST":"$PORT"/"$SERVICE"


function Connected()
SQLConnection <<EOF
select sys_context('USERENV','SERVER_HOST') from dual;
EOF


function GetJMS()
SQLConnection <<EOF
set echo on timing on lines 200 pages 100
select pd.destination from $DB_SCHEMA.pd_notification pd where pd.org_id = '$ORGID';
EOF

TODAY=$(date +"%A %B %d, %Y")
read -r -p $'\n\nWhat is the ORG ID? ' ORGID
read -r -p $'\n\nWhat is the REMOTE QUEUE MANAGER NAME? ' RQM
read -r -p $'\n\nWhat is the IP address of the REMOTE QUEUE MANAGER? ' CONN
read -r -p $'\n\nWhat is the PORT of the REMOTE QUEUE MANAGER? ' PORT
echo -en "* $(whoami)\n* $TODAY\n* MQ Setup $ORGID\n\nDEFINE +\n\tCHANNEL('$RQM.LQML') +\n\tCHLTYPE(SDR) +\n\tCONNAME('$CONN($PORT)') +\n\tXMITQ('BUF.2.$ORGID.XMQ')\n\tCHAUTH(TLS_RSA_WITH_AES_256_CBC_SHA256)\n\nDEFINE +\n\tCHANNEL('LQML.$RQM') +\n\tCHLTYPE(RCVR) +\n\tTRPTYPE(TCP)\n\nDEFINE +\n\tQLOCAL('$RQM') +\n\tTRIGDATA('LQML.$RQM') +\n\tINITQ('SYSTEM.CHANNEL.INITQ') +\n\tTRIGGER USAGE(XMITQ)\n\n" > ~/mqsetup.mqsc

CONNECTED=$(Connected | awk 'NR==16')
echo -en "\n\nHello From: $CONNECTED\n\n"

for JMSDESTINATION in $(GetJMS | awk 'NR>=16&&NR<=24print $1')
    do
        read -r -p $'\n\nWhich REMOTE QUEUE NAME matches with this $JMSDESTINATION?' RNAME
        QDESC=$(echo "$JMSDESTINATION" | tr '.' ' ' | tr '[[:upper:]]' '[[:lower:]]')
        echo -en "\n\nDEFINE +\n\tQR($JMSDESTINATION) +\n\t\tREPLACE DESCR('$ORGID $QDESC Queue') +\n\t\tREPLACE MAXDEPTH(5000) +\n\t\tXMITQ('BUF.2.$ORGID.XMQ') +\n\t\tRNAME('$RNAME') +\n\t\tRQMNAME('$RQM')" >> ~/mqsetup.mqsc
    done

这是我构建的脚本,希望能够自动设置 IBM MQ 队列和通道。我的问题是,在这个脚本之外,我可以直接从 shell 建立一个没有问题的 SQL 会话,只要我输入脚本中看到的变量。我可以调用这些函数,一切都会像我希望的那样返回。当我从脚本中运行完全相同的东西时,我得到超时错误......“Hello From”是空白的,这告诉我没有数据库连接。

我完全不明白为什么它在脚本之外运行良好,但在脚本内部却超时了。

感谢您的眼睛和帮助!

【问题讨论】:

连接部分似乎工作正常;如果您只是调用 Connected,您会看到什么?您在哪里看到超时错误? (即使有连接,你的 awk 模式也没有为我显示任何东西,所以你可能想围绕它进行一些调试?) 您不需要转义此行中的 $ 符号:select pd.destination from $DB_SCHEMA.pd_notification pd where pd.org_id = '$ORGID'; @AlexPoole 是的,假设我已经将变量和函数直接加载到 shell 中,我可以调用函数“Connected”,然后我会立即得到 SQLPlus 标头的输出,即 db-server 主机名,和所有现有的学分。我使用 AWK 将其缩减为仅主机名。当我执行脚本并将所有内容加载到其会话中时,脚本会冻结,就像它试图建立数据库连接一样,但它失败了,因为我作为验证输入的 echo 语句通过打印“Hello From:”而失败(空白处主机名是)。 @BobC ,我不需要转义 $ 因为与 SSH 隧道不同,我希望它在提交之前展开 before (如果我转义它,它会在子shell中运行)......至少这是我的理解......并且它在我编写的与SQLPlus DB交互的其他几个脚本中运行良好。 (这就是为什么这如此令人抓狂的原因,我让它在其他脚本中运行良好!)。 如果连接有效,为什么您认为它会超时? awk 为我提供了一个空白条目,除非我将其更改为 NR==15,但这可能取决于横幅中报告的不同选项。我个人会使用-s 标志,也可能使用-l;并包括set pages 0 feedback off - 所以输出是只是服务器无论如何...... 【参考方案1】:

您正在覆盖一个变量值。你在脚本的顶部有这个:

PORT="5678"

但稍后你会这样做:

read -r -p $'\n\nWhat is the PORT of the REMOTE QUEUE MANAGER? ' PORT

它会用在那里输入的任何内容覆盖您的 5678 值。该端口可能根本没有在 DB 服务器上侦听,或者可能正在执行其他操作,或者如果您不输入值,则连接时它将默认为端口 1521。但无论哪种方式,连接都会失败,或者快或慢,具体取决于端口状态(例如,如果防火墙阻止它,可能会更慢)。

如果您通过在read 调用之前添加Connected 调用来测试连接(就像我最初所做的那样),那么它似乎工作正常;但是读取后的连接不起作用,因为它尝试连接的端口值现在是错误的。

为这两个变量使用不同的名称,例如RQ_PORT 用于第二个 - 在其 read 命令和随后创建的 ~/mqsetup.mqsc 文件中。

您可能还会发现在 SQL*Plus 调用中添加 -l 标志很有用,这样如果连接由于某种原因失败,它就不会重新提示输入凭据,这在某些情况下会使脚本出现一直挂到你按回车几次。


与问题没有直接关系,但是在自动化这样的事情时,我通常还使用-s 标志来抑制横幅(可能因环境而异);如果您只对捕获查询输出感兴趣,我通常会关闭标题和/或分页,并关闭反馈,并且通常将 SQL*Plus 设置为尽可能少地产生噪音 - 它可以更轻松地解析出有趣的部分.

【讨论】:

这完全正确!天啊,我不敢相信我看过去了!非常感谢你抓住它。此外,不知道选项“-S”和“-L”......这些会有所帮助。谢谢!

以上是关于无法从 BASH 脚本中建立 Oracle SQL 会话的主要内容,如果未能解决你的问题,请参考以下文章

在 bash 脚本中循环 sql 查询

如何从 Mac 上的 bash 脚本调用 ./snowsql 文件?

关于如何在 Oracle 数据库中使用 VBA 执行 SQL 脚本的建议

从 Bash 或 Perl 脚本运行 SQL 语句?

oracle导入

无法在 Oracle 匿名块中调用和执行 .sql 脚本文件