如何在Bash脚本中运行SQL命令并将该命令的输出保存到变量中

时间:2012-05-29 19:28:03

标签: sql oracle bash

我希望将一些Oracle组件包含在一个Bash脚本中,该脚本将执行一系列目标:

  1. 以root用户身份登录远程服务器(我的Oracle DB所在的位置)。
  2. 执行“su - oracle”。
  3. 以特定的Oracle用户身份登录sqlplus环境。
  4. 执行SQL select命令并将该命令的输出存储到变量中。
  5. 在Bash shell中显示该变量的结果。
  6. 我在这里看了几个关于stackoverflow的例子,其中许多似乎都在执行一个命令,但不一定详细说明如何向用户显示输出(尽管我还在研究一些)。例如,假设事先设置了所有密钥交换,则可以使用以下方法:

    #!/bin/sh
    ssh -q root@5.6.7.8
    sqlplus ABC/XYZ@core <<ENDOFSQL
    select CREATE_DATE from PREPAID_SUBSCRIBER where MSISDN='12345678912';
    exit;
    ENDOFSQL
    

    相反,以下是我尝试设置的方法:

    #!/bin/sh
    datasource_name=`echo "select CREATE_DATE from PREPAID_SUBSCRIBER where MSISDN='12345678912';" | ssh -q 5.6.7.8 "su - oracle -c 'sqlplus -S ABC/XYZ@core'" | tail -2 | head -1`
    

    理想情况下,datasource_name变量现在应该采用值:

    no rows selected
    

    如果表格中有条目:

    CREATE_DATE
    -------------------
    07-06-2009 18:04:48
    

    tail和head命令用于删除输出中的空行,ssh -q和sqlplus -S选项用于忽略警告。

    但是,当我运行该命令时,执行:

    echo "${datasource_name}"
    

    我明白了......

    警告:无法访问tty(错误的文件描述符)。 因此在这个shell中没有作业控制。

    ...而不是上面两个输出中的一个。如果我理解正确,这是一个警告,可能是由于是否使用了特定的shell引起的,但大多数在线资源表明这可以忽略。关于这个警告的好处是看起来上面我的命令实际上正在运行并将“something”存储到datasource_name中,但它不是我想要的。

    现在为了简化这个问题,我注意到当我只是尝试从运行bash脚本的框中的远程机器上的oracle中获取相同的tty警告时:

    ssh root@5.6.7.8 "su - oracle"
    Warning: no access to tty (Bad file descriptor).
    Thus no job control in this shell.
    

    如果我执行以下操作,我实际上已成功进入sqlplus环境而没有任何问题:

    ssh -q root@5.6.7.8 "su - oracle -c 'sqlplus ABC/XYZ@core'"
    
      

    SQL * Plus:版本9.2.0.4.0 - 生产于2012年5月29日星期二12:35:06

         

    版权所有(c)1982,2002,Oracle Corporation。保留所有权利。

         

    连接到:Oracle数据库10g企业版发行版   10.2.0.4.0 - 使用分区,真实应用集群,OLAP,数据挖掘和实际应用测试选项进行64位生产

         

    SQL&GT;

    如果我理解为什么上面的问题正在发生,我可能会弄清楚如何使我的脚本正常工作。任何建议将不胜感激!谢谢。

2 个答案:

答案 0 :(得分:1)

将第一行更改为:

ssh -t  root@5.6.7.8 "su - oracle"     

得到一个tty,看看这是否适合你。

你可以在你的脚本中做的另一件事是将stderr重定向到你的变量,如果你想在变量中看到它,这对你来说似乎并非如此,尽管我已经这样做了过去在某些情况下。下面的评论中有一个例子。

答案 1 :(得分:1)

这是MySQL的示例脚本,但可以为Oracle轻松编辑:

#!/bin/bash

remote=oracle@5.6.7.8

ssh -q -t $remote <<EOF
bash <<EOFBASH
mysql <<ENDOFSQL>/tmp/out
show databases;
ENDOFSQL
EOFBASH
EOF

scp $remote:/tmp/out /tmp/out
ds=$(</tmp/out)

cat <<EOF
START OUTPUT
$ds
END OUTPUT
EOF

rm /tmp/out

经过测试,效果很好。而不是使用su - oracle,尝试直接ssh到oracle用户;)