sql - 从 PL/SQL 调用 shell 脚本,但 shell 以网格用户而不是 oracle 的身份执行

标签 sql linux oracle bash shell

我正在尝试使用 Runtime.getRuntime().exec 从 Oracle 数据库内部执行一个 shell 脚本。

在 Red Hat 5.5 上运行的 Oracle 11.2.0.4 EE


CREATE OR REPLACE procedure pr_executa_host(p_cmd varchar2)
    as language java name 'Util.RunThis(java.lang.String)';
/

public class Util extends Object
{

  public static int RunThis(java.lang.String args)
  {
  Runtime rt = Runtime.getRuntime();
  int        rc = -1;

  try
  {
     Process p = rt.exec(args);

     int bufSize = 4096;
     BufferedInputStream bis =
      new BufferedInputStream(p.getInputStream(), bufSize);
     int len;
     byte buffer[] = new byte[bufSize];

     // Echo back what the program spit out
     while ((len = bis.read(buffer, 0, bufSize)) != -1)
        System.out.write(buffer, 0, len);

     rc = p.waitFor();
  }
  catch (Exception e)
  {
     e.printStackTrace();
     rc = -1;
  }
  finally
  {
     return rc;
  }
  }
}
/

在 java 上授予 db 用户 SCOTT 的权限:


kind    grantee    type    name    action

GRANT    SCOTT    java.io.FilePermission    /webstart/mn500/*    readFileDescriptor
GRANT    SCOTT    java.io.FilePermission    /webstart/mn500/*    read,write,execute
GRANT    SCOTT    java.io.FilePermission    /webstart/mn500/*    writeFileDescriptor
GRANT    SCOTT    java.io.FilePermission  /webstart/mn500/CONCLUIDO/MN457560/executa.sh execute
GRANT    SCOTT    java.lang.RuntimePermission    *    writeFileDescriptor
GRANT    SCOTT    java.lang.RuntimePermission /webstart/mn500/CONCLUIDO/MN457560/executa.sh    execute

shell 脚本 executa.sh,这是我要执行的脚本:


#!/bin/sh
echo i am `/usr/bin/whoami`
echo environment `/bin/env`
/bin/date>>/webstart/mn500/CONCLUIDO/MN457560/test.txt

目录权限:


p08[oracle] $ ls -larth /webstart/mn500/CONCLUIDO/MN457560
-rw-r--r--   1 oracle oinstall    1 Jul 29 12:03 test.txt
-rwxr-xr-x   1 oracle orafiles  430 Jul 29 12:04 executa.sh
drwxr-xr-x   2 oracle orafiles 4.0K Jul 29 12:04 .

问题是,当我执行过程 pr_executa_host 时,它以 grid os 运行 shell 脚本 用户,不是甲骨文! (虽然它保留了 oracle 环境变量,就像它做了 'su grid -m' 在执行 shell 脚本之前)

由于 grid 对目录和文件都没有写权限,因此脚本不 做任何事情,测试文件保持不变。看一看:


begin
  dbms_java.set_output(1000000);
  pr_executa_host('/webstart/mn500/CONCLUIDO/MN457560/executa.sh');
  dbms_lock.sleep(2);
end;
/

i am grid
environment HOSTNAME=p08.XXXXXXXXXXXX.com.br SHELL=/bin/bash TERM=xterm HISTSIZE=1000 
SSH_CLIENT=10.141.112.28 56029 22 NLS_LANG=AMERICAN_AMERICA.WE8MSWIN1252 QTDIR=/usr/lib64/qt-3.3 
QTINC=/usr/lib64/qt-3.3/include SSH_TTY=/dev/pts/0 USER=oracle 
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;0
1:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01
;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*
.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.tbz=01;31:*.tbz2=01;31:*.bz=01;31
:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7
z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01
;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;3
5:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*
.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=
01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35
:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.a
ac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=
01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36: ORACLE_SID=sigepshm 
ORACLE_BASE=/oracle ORACLE_HOSTNAME=P08 PATH= MAIL=/var/spool/mail/oracle 
TNS_ADMIN=/grid/product/11.2.0/grid/network/admin PWD=/oracle/product/11.2.0/db/dbs 
KDE_IS_PRELINKED=1 LANG=en_US.UTF-8 ORA_NET2_DESC=27,30 KDEDIRS=/usr ORACLE_TERM=xterm 
ORACLE_SPAWNED_PROCESS=1 HISTCONTROL=ignoredups SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass 
HOME=/home/oracle SHLVL=2 GRID_HOME=/oracle/product/11.2.0/grid LOGNAME=oracle CVS_RSH=ssh 
QTLIB=/usr/lib64/qt-3.3/lib SSH_CONNECTION=10.141.112.28 56029 10.147.0.8 22 
CLASSPATH=/oracle/product/11.2.0/db/JRE:/oracle/product/11.2.0/db/jlib:/oracle/product/11.2.0/db/rdb
ms/jlib LESSOPEN=|/usr/bin/lesspipe.sh %s DISPLAY=localhost:10.0 
ORACLE_HOME=/oracle/product/11.2.0/db G_BROKEN_FILENAMES=1 _=/bin/env

为什么数据库里面的java是以grid用户调用unix命令,而不是oracle?

非常感谢您的帮助, 偷走

最佳答案

正如评论中所指出的,问题是 Runtime.getRuntime().exec 通过 EXTPROC 运行,因此通过 Grid Listener。由于我们在新配置上的 DB 和 GRID 之间有操作系统用户隔离,这引发了 FS 上的权限问题。

解决这个问题的方法之一是:

  • 修复 FS 权限,让 grid 用户写入文件,并将 umask 更改为 774 或 664 之类的东西,这样 grid 和 oracle 用户以后都可以修改文件;

  • 更改 sudoers 文件并允许网格在没有密码的情况下像 oracle 一样执行所需的命令,并更改 shell 脚本以包含 sudo;

  • 在另一个端口的 DB Home 上创建一个新的监听器,并更改 TNSNAMES.ORA 条目以指向新端口。然后 extproc 将作为 OS 用户 oracle 执行。您将必须手动编辑 $OH 上的 LISTENER.ORA 并使用 lsnrctl 启动它,因为使用 srvctl 注册的监听器将始终由 grid 启动;

  • 将主要监听器更改为数据库主页。我不建议这样做(见上文)。

[编辑] 正如@AlexPoole 和@jonearles 所指出的,还有另外两个选项不适合我的情况,但可能适合其他人:

  • 如果您在 sqlplus 上本地运行脚本,设置 ORACLE_SID,FS 访问将由运行 sqlplus 的操作系统用户进行。因此,您可以以 oracle 或其他用户身份运行并修复 FS 权限;
  • 如果您以 SYS 身份在 dbms_job scheduler 上安排作业,则该任务将由 oracle 执行(此行为可能取决于版本,因此需要进一步测试)。

问候,

丹尼尔·斯托夫

关于sql - 从 PL/SQL 调用 shell 脚本,但 shell 以网格用户而不是 oracle 的身份执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25021416/

相关文章:

sql - Oracle 将 NCLOB 数据解析到输出或新表

c# - 在 C# 中的存储过程中使用全局临时表

一列的 SQL Server 不同联合

sql - SQL 结果什么时候可以包含重复项?

java - 使用映射到一个表的实体

linux - 我可以通过 sudo -u 伪装的身份列表

sql - 如果不存在则删除表空间

sql - 让 Doctrine 在 INSERT INTO 期间跳过只读字段/列

linux - GCC 选项的 -shared 和 -Wl,-shared 的区别

php - UTF-8贯穿始终