我正在尝试使用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过程时,它将shell脚本作为grid os运行 用户,而不是oracle! (虽然它保留了oracle环境变量,就像它做了'su grid -m' 在执行shell脚本之前)
由于网格既没有对目录也没有文件的写权限,因此脚本没有 做任何事情,测试文件保持不变。看看:
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调用unix命令为grid用户,而不是oracle?
非常感谢你的帮助, Stolf
答案 0 :(得分:3)
正如评论中所指出的那样,问题是Runtime.getRuntime()。exec在EXTPROC中运行,因此通过Grid Listener运行。由于我们的新配置在DB和GRID之间存在操作系统用户隔离,因此会引发FS上的权限问题。
对此的解决方案之一是:
修复FS权限,让网格用户编写文件并将umask更改为774或664,这样网格和oracle用户以后都可以修改文件;
更改sudoers文件并允许网格执行oracle所需的命令而无需密码,并更改shell脚本以包含sudo;
在另一个端口上的DB Home上创建一个新侦听器,并将TNSNAMES.ORA条目更改为指向新端口。然后extproc将作为OS用户oracle执行。您必须在$ OH上手动编辑LISTENER.ORA并使用lsnrctl启动它,因为使用srvctl注册的侦听器将始终由网格启动;
将主侦听器更改为db home。我不推荐(见上面的项目)。
[编辑] 正如@AlexPoole和@jonearles所指出的,还有另外两个选项不适合我的情况,但也可能适用于其他选项:
此致
Daniel Stolf
答案 1 :(得分:1)
在进一步调查中,它以启动会话的OS用户身份运行脚本;但是服务器用户,而不是osuser
中的客户v$session
。
如果您通过SQL * Plus本地连接,而不通过SQL * Net,则shell脚本将作为您自己的操作系统用户运行,而不是grid
或 oracle
,除非你作为其中之一登录了这个盒子。因此,当我以自己的身份执行该过程时,脚本会报告i am apoole
。
当你远程运行时,会话的OS用户是监听器所有者,默认情况下,网格环境中的用户将是grid
。并且,当启动侦听器时,您会看到grid
用户的环境。
因此,如果您要通过SQL * Net连接的客户端手动执行此操作,那么您自己的答案中的选项是有效的。您可以将数据库侦听器移动到oracle
帐户下运行,或者在该帐户下创建一个新侦听器,然后通过该帐户进行连接。然后,当从通过该侦听器连接的任何会话调用时,脚本将以oracle
执行。或者让操作系统权限/ sudo为你工作。
如果您将或不可能通过SQL * Net从本地会话执行它,那么您需要使操作系统权限对任何可能调用它的用户有效 - 假设您不能运行来自oracle
帐户启动的SQL * Plus。听众不是图片的一部分,因此grid
用户不是一个因素。
这是它作为匿名块运行的时候;正如@jonearles在对该问题的评论中指出的那样,预定作业的行为是不同的。默认情况下,它会以nobody
执行脚本,这意味着您必须更多地放宽操作系统权限。