Nagarajan, May 30, 2001 - 3:06 pm UTC
very useful material. Thanks for the same
Exactly what I needed to see
B.Wisniewski, June 04, 2001 - 8:22 am UTC
This is exactly what I needed to see in an example of interacting with the operating system. Trying to persuade the developers to use Java vs Perl and this is what I needed.
Thanks again.
Mark Penny, July 27, 2001 - 5:37 am UTC
I had never imagined that this could be done so easily. Thank you.
great answer
Sharon, October 03, 2001 - 10:51 am UTC
Great material , it's exactlly what I was looking for
10x you a lot
A reader, November 21, 2001 - 8:48 pm UTC
hi tom
your reply on extrnal procedure works
Thanks
I am also trying to run executable from java
i am getting this error
I am running Pesonal Oracle 8.1.7 on windows 98
SQL> exec rc('c:\windows\command /c dir');
java.io.IOException
at oracle.aurora.java.lang.OracleProcess.create(OracleProcess.java)
at oracle.aurora.java.lang.OracleProcess.construct(OracleProcess.java)
at java.lang.Runtime.execInternal(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at Util.RunThis(Util:11)
PL/SQL procedure successfully completed.
November 22, 2001 - 8:45 am UTC
Ok, is there a c:\windows\command.exe ?
do a dir c:\windows\command.*
show us the entire example from the dbms_java calls to the create or replace and compile java source to the call you are doing itself.
A reader, November 22, 2001 - 10:03 am UTC
hi tom
it was dir c:\windows\command.com
when i run
exec rc('c:\windows\command.com /c dir');
it never come back
i examined udump file it looks like
Dump file d:\oracle\admin\swami\udump\ORA10653.TRC
Thu Nov 22 09:34:37 2001
ORACLE V8.1.7.0.0 - Production vsnsta=0
vsnsql=e vsnxtr=3
Windows 95 V4.10, OS V192.0, CPU type 586
Oracle8i Personal Edition Release 8.1.7.0.0 - Production
JServer Release 8.1.7.0.0 - Production
Windows 95 V4.10, OS V192.0, CPU type 586
Instance name: swami
Redo thread mounted by this instance: 1
Oracle process number: 13
Windows thread id: -710243, image: ORACLE.EXE
*** 2001-11-22 09:34:37.720
*** SESSION ID:(17.10) 2001-11-22 09:34:37.610
Specified COMMAND search directory bad Microsoft(R) Windows 98
(C)Copyright Microsoft Corp 1981-1998. D:\Oracle\Ora81\DATABASE>
any idea.
Thanks
November 22, 2001 - 10:40 am UTC
Well, it looks like it just started up a command shell -- did not process the "/c dir" part of it (hence the apparent HANG -- it was waiting for someone to type "exit".
what happens if you just enter:
c:\windows\command.com /c dir
on the dos prompt itself. does that work?
what if you create a script:
do_dir.bat:
@echo off
dir
and run that instead?
but....
Connor, November 22, 2001 - 10:20 am UTC
who is Steve ?
:-)
November 22, 2001 - 10:41 am UTC
Thats a darn good question -- never noticed that Henk-Jan called me "steve" :)
A reader, November 22, 2001 - 10:58 am UTC
hi tom,
i ran
c:\windows\command.com /c dir
on dos prompt it works fine
and i also created do_dit.bat and it also works fine
thanks
November 22, 2001 - 11:06 am UTC
did you call the do_dir.bat from the java stored procedure -- if so, thats your solution. You see -- this is purely a "command.com" issue here -- we are getting a command.com error "search path invalid (sounds like a bad COMSPEC or something, been a really long time since I worked with dos stuff like that).
re: steve
Mark A. Williams, November 22, 2001 - 11:05 am UTC
I think 'Steve' is Tom's alter ego -- you know, the one who is answering questions and such on Thanksgiving! Thought you (Tom) were taking a break? OK, so I'm *reading* AskTom on Thanksgiving... but that's just because I haven't had the turkey yet.
A reader, November 22, 2001 - 11:27 am UTC
hi tom
Sorry for disturbance on thanks giving but my problem is critical i have to implement this on coming MONDAY
when i run
exec rc('c:\windows\command.com /c dir');
it never come back
THIS TIME I SET SQL_TRACE = TRUE
AND LOG FILE IS AS FOLLOWS
I KILLED SESSION FOR THREE TIMES AND CHECK LOG FILE EACH TIME. IT IS SIMILER EVERY TIME
Dump file d:\oracle\admin\swami\udump\ORA51445.TRC
Thu Nov 22 11:16:57 2001
ORACLE V8.1.7.0.0 - Production vsnsta=0
vsnsql=e vsnxtr=3
Windows 95 V4.10, OS V192.0, CPU type 586
Oracle8i Personal Edition Release 8.1.7.0.0 - Production
JServer Release 8.1.7.0.0 - Production
Windows 95 V4.10, OS V192.0, CPU type 586
Instance name: swami
Redo thread mounted by this instance: 1
Oracle process number: 10
Windows thread id: -341771, image: ORACLE.EXE
*** 2001-11-22 11:16:57.070
*** SESSION ID:(11.3) 2001-11-22 11:16:57.010
APPNAME mod='SQL*Plus' mh=3669949024 act='' ah=4029777240
=====================
PARSING IN CURSOR #1 len=35 dep=0 uid=18 oct=42 lid=18 tim=0 hv=2767092717 ad='4332a9c'
alter session set sql_trace = true
END OF STMT
EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=4,tim=0
=====================
PARSING IN CURSOR #1 len=87 dep=0 uid=18 oct=47 lid=18 tim=0 hv=3739629728 ad='433c588'
BEGIN RC('c:\windows\command.COM /c exp scott/tiger file=c:\xx.dmp tables=emp'); END;
END OF STMT
PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=4,tim=0
=====================
PARSING IN CURSOR #2 len=64 dep=1 uid=0 oct=2 lid=0 tim=0 hv=3686129482 ad='477a920'
insert into javasnm$(short, longname, longdbcs) values(:1,:2,:3)
END OF STMT
PARSE #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=0,tim=0
=====================
PARSING IN CURSOR #3 len=46 dep=1 uid=0 oct=3 lid=0 tim=0 hv=2044415509 ad='475d6b4'
select longname from javasnm$ where short = :1
END OF STMT
PARSE #3:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
EXEC #3:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
FETCH #3:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
EXEC #3:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
FETCH #3:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
EXEC #3:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
FETCH #3:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
EXEC #3:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
FETCH #3:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
EXEC #3:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
FETCH #3:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
EXEC #3:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
FETCH #3:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
EXEC #3:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
FETCH #3:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
EXEC #3:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
FETCH #3:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
EXEC #3:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
FETCH #3:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
=====================
PARSING IN CURSOR #4 len=57 dep=1 uid=0 oct=3 lid=0 tim=0 hv=467722929 ad='46be564'
SELECT max(version) FROM "SYS"."JAVA$POLICY$SHARED$TABLE"
END OF STMT
PARSE #4:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
EXEC #4:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=1,cu=4,mis=0,r=1,dep=1,og=4,tim=0
STAT #4 id=1 cnt=1 pid=0 pos=0 obj=0 op='SORT AGGREGATE '
STAT #4 id=2 cnt=2 pid=1 pos=1 obj=16803 op='TABLE ACCESS FULL JAVA$POLICY$SHARED$TABLE '
=====================
PARSING IN CURSOR #4 len=57 dep=1 uid=0 oct=3 lid=0 tim=0 hv=467722929 ad='46be564'
SELECT max(version) FROM "SYS"."JAVA$POLICY$SHARED$TABLE"
END OF STMT
PARSE #4:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
EXEC #4:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=1,cu=4,mis=0,r=1,dep=1,og=4,tim=0
STAT #4 id=1 cnt=1 pid=0 pos=0 obj=0 op='SORT AGGREGATE '
STAT #4 id=2 cnt=2 pid=1 pos=1 obj=16803 op='TABLE ACCESS FULL JAVA$POLICY$SHARED$TABLE '
EXEC #3:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
FETCH #3:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
EXEC #3:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
FETCH #3:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
EXEC #3:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
FETCH #3:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
=====================
PARSING IN CURSOR #4 len=147 dep=1 uid=0 oct=3 lid=0 tim=0 hv=3013728279 ad='468ad64'
select privilege#,level from sysauth$ connect by grantee#=prior privilege# and privilege#>0 start with (grantee#=:1 or grantee#=1) and privilege#>0
END OF STMT
PARSE #4:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
EXEC #4:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=6,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=6,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=6,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=0,dep=1,og=4,tim=0
STAT #4 id=1 cnt=37 pid=0 pos=0 obj=0 op='CONNECT BY '
STAT #4 id=2 cnt=20 pid=1 pos=1 obj=0 op='CONCATENATION '
STAT #4 id=3 cnt=1 pid=2 pos=1 obj=102 op='INDEX RANGE SCAN '
STAT #4 id=4 cnt=20 pid=2 pos=2 obj=102 op='INDEX RANGE SCAN '
STAT #4 id=5 cnt=19 pid=1 pos=2 obj=83 op='TABLE ACCESS BY USER ROWID SYSAUTH$ '
STAT #4 id=6 cnt=55 pid=1 pos=3 obj=102 op='INDEX RANGE SCAN '
=====================
PARSING IN CURSOR #4 len=147 dep=1 uid=0 oct=3 lid=0 tim=0 hv=3013728279 ad='468ad64'
select privilege#,level from sysauth$ connect by grantee#=prior privilege# and privilege#>0 start with (grantee#=:1 or grantee#=1) and privilege#>0
END OF STMT
PARSE #4:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
EXEC #4:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=6,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=6,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=6,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=0,dep=1,og=4,tim=0
STAT #4 id=1 cnt=37 pid=0 pos=0 obj=0 op='CONNECT BY '
STAT #4 id=2 cnt=20 pid=1 pos=1 obj=0 op='CONCATENATION '
STAT #4 id=3 cnt=1 pid=2 pos=1 obj=102 op='INDEX RANGE SCAN '
STAT #4 id=4 cnt=20 pid=2 pos=2 obj=102 op='INDEX RANGE SCAN '
STAT #4 id=5 cnt=19 pid=1 pos=2 obj=83 op='TABLE ACCESS BY USER ROWID SYSAUTH$ '
STAT #4 id=6 cnt=55 pid=1 pos=3 obj=102 op='INDEX RANGE SCAN '
=====================
PARSING IN CURSOR #4 len=147 dep=1 uid=0 oct=3 lid=0 tim=0 hv=3013728279 ad='468ad64'
select privilege#,level from sysauth$ connect by grantee#=prior privilege# and privilege#>0 start with (grantee#=:1 or grantee#=1) and privilege#>0
END OF STMT
PARSE #4:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
EXEC #4:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=0,dep=1,og=4,tim=0
STAT #4 id=1 cnt=14 pid=0 pos=0 obj=0 op='CONNECT BY '
STAT #4 id=2 cnt=4 pid=1 pos=1 obj=0 op='CONCATENATION '
STAT #4 id=3 cnt=1 pid=2 pos=1 obj=102 op='INDEX RANGE SCAN '
STAT #4 id=4 cnt=4 pid=2 pos=2 obj=102 op='INDEX RANGE SCAN '
STAT #4 id=5 cnt=3 pid=1 pos=2 obj=83 op='TABLE ACCESS BY USER ROWID SYSAUTH$ '
STAT #4 id=6 cnt=25 pid=1 pos=3 obj=102 op='INDEX RANGE SCAN '
EXEC #3:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
FETCH #3:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
=====================
PARSING IN CURSOR #4 len=147 dep=1 uid=0 oct=3 lid=0 tim=0 hv=3013728279 ad='468ad64'
select privilege#,level from sysauth$ connect by grantee#=prior privilege# and privilege#>0 start with (grantee#=:1 or grantee#=1) and privilege#>0
END OF STMT
PARSE #4:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
EXEC #4:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=1,dep=1,og=4,tim=0
FETCH #4:c=0,e=0,p=0,cr=4,cu=0,mis=0,r=0,dep=1,og=4,tim=0
STAT #4 id=1 cnt=14 pid=0 pos=0 obj=0 op='CONNECT BY '
STAT #4 id=2 cnt=4 pid=1 pos=1 obj=0 op='CONCATENATION '
STAT #4 id=3 cnt=1 pid=2 pos=1 obj=102 op='INDEX RANGE SCAN '
STAT #4 id=4 cnt=4 pid=2 pos=2 obj=102 op='INDEX RANGE SCAN '
STAT #4 id=5 cnt=3 pid=1 pos=2 obj=83 op='TABLE ACCESS BY USER ROWID SYSAUTH$ '
STAT #4 id=6 cnt=25 pid=1 pos=3 obj=102 op='INDEX RANGE SCAN '
IT HANGS HERE EVERY TIME
November 23, 2001 - 9:44 am UTC
I already diagnosed this! It is NOT HANGNING IN ORACLE. You put up this dump file before:
i examined udump file it looks like
.....
Dump file d:\oracle\admin\swami\udump\ORA10653.TRC
Thu Nov 22 09:34:37 2001
ORACLE V8.1.7.0.0 - Production vsnsta=0
vsnsql=e vsnxtr=3
Windows 95 V4.10, OS V192.0, CPU type 586
Oracle8i Personal Edition Release 8.1.7.0.0 - Production
JServer Release 8.1.7.0.0 - Production
Windows 95 V4.10, OS V192.0, CPU type 586
Instance name: swami
Redo thread mounted by this instance: 1
Oracle process number: 13
Windows thread id: -710243, image: ORACLE.EXE
*** 2001-11-22 09:34:37.720
*** SESSION ID:(17.10) 2001-11-22 09:34:37.610
Specified COMMAND search directory bad Microsoft(R) Windows 98
(C)Copyright Microsoft Corp 1981-1998. D:\Oracle\Ora81\DATABASE>
any idea.
.......
When you are running "command /c dir" -- dos is messing up. You see the error message there "Specified COMMAND search directory bad" and a command prompt. That is your HANG.
command.com is running,
It is messing up.
It is dumping you at the command prompt -- waiting for you to type something in.
Unfortunately for you - this command prompt is in the background, you cannot see it, you cannot type into it. It will sit there forever.
This is NOT hanging in the database. This is hanging in DOS.
Did you try the .bat file as I suggested. If that works -- that is in fact your solution. If it doesn't, you'll have to find out what that error message is and how to fix it. I don't have windows98 to test with.
A reader, November 24, 2001 - 5:06 pm UTC
hi tom
finally i am able to run OS command from pl/sql.but from
Windws NT not Windows 98.
Now I can run os command using extrnal procedure
and Java stored procedure.
Thank you very much for your co-opration
Encountering some limitations
Andrew, November 29, 2001 - 3:59 pm UTC
Tom
Thanks for the great code, but I'm hitting limitations using '>', '|' and other metacharacters. Please could you explain why my attempts fail. I can only overcome the problem by writing the string I want to execute to a script (using utl_file, doing a chmod +x on that and then executing it). As you can see the use of '|' returns and error, the use of '>' is ignored.
1.) Granted the following privs from sys:
begin
dbms_java.grant_permission
('SCOTT',
'java.io.FilePermission',
'/tmp/*',
'execute');
dbms_java.grant_permission
('SCOTT',
'java.io.FilePermission',
'/usr/bin/*',
'execute');
dbms_java.grant_permission
('SCOTT',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
-- try to accomodate input redirection
dbms_java.grant_permission
('SCOTT',
'java.lang.RuntimePermission',
'*',
'readFileDescriptor' );
-- try to accomodate input/output redirection
('SCOTT',
'java.io.FilePermission',
'/tmp/*',
'read,write');
-- commit;
end;
/
2.) changed RC to output the return code:
CREATE OR REPLACE procedure RC(p_cmd in varchar2)
as
x number;
begin
x := run_cmd(p_cmd);
DBMS_OUTPUT.PUT_LINE ( 'run_cmd returned : '||rpad(x, 3, ' ')||' for '|| p_cmd);
end;
/
3.) the results
SQL> set serveroutput on
SQL>
SQL> set serveroutput on
SQL>
SQL> declare
2 dummy varchar2(50);
3 begin
4 dbms_output.enable(1000000);
5 dbms_java.set_output(1000000);
6
7 -- the following work fine
8 -- rc('/usr/bin/ps -ef');
9 -- rc('/usr/bin/pwd');
10 -- rc('/usr/bin/touch /tmp/t.txt');
11
12 -- the following don't work
13 rc('/usr/bin/ps -ef | /usr/bin/grep oracle');
14 rc('/usr/bin/pwd > /tmp/pwd.log');
15 -- rc('/usr/bin/ksh -c "/usr/bin/pwd > /tmp/pwd.log"');
16 end;
17 /
run_cmd returned : 1 for /usr/bin/ps -ef | /usr/bin/grep oracle
/apps/oracle/product/8.1.7/dbs
run_cmd returned : 0 for /usr/bin/pwd > /tmp/pwd.log
PL/SQL procedure successfully completed.
4.) From Unix:
ls -ltr /tmp/pwd.log
/tmp/pwd.log: No such file or directory
November 30, 2001 - 8:27 am UTC
What I believe your issue is is that we wrote this tiny routine to run "A" program. You are not running "A" program -- you are running a shell specific command. This is like someone on windows trying to run "dir", "dir" is not a program -- its an internal command. similarly, ps -ef | grep oracle is not a command -- its an internal command to your shell that says "start ps, redirect its stdout, start grep, redirect its stdin".
you would need to run a SHELL that understands "|" and ">", something like:
sh -c 'ps -ef | grep oracle'
BUT -- then you would need execute on /bin/sh, with that you can run ANY command as the user "oracle" (or who ever starts the database). That would let you for example "sh -c rm -rf /*" and erase everything oracle is allowed to erase. So, my real suggestion would be to create a script that has the commands you want to execute and you run THAT script from the database. Give your self the permission to run that one command -- not /bin/sh
Tom, sorry for the mixup.
Henk-Jan Korpel, December 17, 2001 - 5:58 am UTC
He Tom,
Sorry, for the mixup with Steve (Feuerstein, that is) whose stuff I was studying at that time. I just saw it today, hope this clears it.
Regards
Henk-Jan
"Java procedure for host calls on Unix environment", version 8.1.6
Randy Bradley, January 16, 2002 - 6:58 pm UTC
Tom,
I found this information to be very helpful. The step-by-step instructions were easy to follow. I have a question about using the ftp command instead of the ps command. When I run the ps command everything work fine, but when I run the ftp command ("/usr/bin/ftp -vin < /public/parfile.txt"), the procedure just hangs.
What's seems to be causing this problem. I did assign execute permissions via the dbms_java package.
One more thing... I'm running 8.1.7 (64-bit) on HP-UX 11.00 (64-bit).
January 17, 2002 - 7:42 am UTC
ftp is waiting for the username and password to be entered and ftp refuses to read this from stdin as you are trying (i assume you have the username/password in the parfile.txt)
Do a man on netrc to see how to setup a .netrc (in the ORACLE account -- could be somewhat "dangerous").
A better approach might be to use some java classes that let you PROCEDURALLY do an ftp from java -- in that fashion, you can alleviate the inherit security issues with the .netrc file solution.
special characters >, >>, |, < etc.
A reader, January 17, 2002 - 12:33 pm UTC
I bet the above reader will need to do the FTP from a shell script if he wants to use '<'. I had a similar problem higher up in this thread.
January 17, 2002 - 1:59 pm UTC
Absolutely correct -- I didn't even read that far into the command -- that will be the next problem they hit.
Java procedure for host calls on Unix environment", version 8.1.6
Randy Bradley, January 17, 2002 - 12:43 pm UTC
Your information about using .netrc worked to some degree. I woks when I run the ftp command from the unix prompt, but it still hangs when I attempt to execute from SQL*PLUS. I hope you can help me resolve yet another issue.
Thanks!
January 17, 2002 - 2:00 pm UTC
See above...
Java procedure for host calls on Unix environment", version 8.1.6
Randy Bradley, January 17, 2002 - 4:56 pm UTC
I created shell script and I execute the shell script from with the procedure. Thanks for all the help.
Randy
Standard shell script...
A reader, January 17, 2002 - 6:05 pm UTC
In my comments higher up I referred to writing the command to a file, doing a chmod +x etc. Obviously that's only if you don't know the command you want to run. Creating a standard ftp shell script with predefined input parms is better. Maybe the way you implemented it?? From what I can remember the DBMS_PIPE solution (see this site) doesn't have the special character limitation. Java solution just seems neater.
9i ?
Connor, February 07, 2002 - 7:20 am UTC
Apologies for my total lack of java knowledge (I'm getting there...), but your example (which worked fine in 8i) appears to bomb out under my 9i version. Could you post if the same code works under one of your 9i versions?
SQL> variable x number;
SQL> set serveroutput on
SQL> exec dbms_java.set_output(100000);
SQL> exec :x := RUN_CMD('/usr/bin/ls');
java.lang.ArrayIndexOutOfBoundsException
at Util.RunThis(Util:14)
Cheers
Connor
February 11, 2002 - 7:33 am UTC
I just removed the String array definition on the PL/SQL wrapper
function and the Java method. I've included all the code again (and an
example) below. I do not fully know why it worked in 8i.
My assumption is that the JVM-PL/SQL data type pickler may have
automatically promoted non-array types to arrays when required. Or 8i
was less exacting that in 9i.
ops$tkyte@ORA9I.WORLD> begin
2 dbms_java.grant_permission
3 ('RT_TEST',
4 'java.io.FilePermission',
5 '/usr/bin/ls',
6 'execute');
7
8 dbms_java.grant_permission
9 ('RT_TEST',
10 'java.lang.RuntimePermission',
11 '*',
12 'writeFileDescriptor' );
13 end;
14 /
PL/SQL procedure successfully completed.
ops$tkyte@ORA9I.WORLD> connect rt_test/rt_test
Connected.
ops$tkyte@ORA9I.WORLD> @login
rt_test@ORA9I.WORLD> create or replace and compile
2 java source named "Util"
3 as
4 import java.io.*;
5 import java.lang.*;
6
7 public class Util extends Object
8 {
9 public static int RunThis(String args)
10 {
11 Runtime rt = Runtime.getRuntime();
12 int rc = -1;
13
14 try
15 {
16 Process p = rt.exec(args);
17
18 int bufSize = 4096;
19 BufferedInputStream bis =
20 new BufferedInputStream(p.getInputStream(), bufSize);
21 int len;
22 byte buffer[] = new byte[bufSize];
23
24 // Echo back what the program spit out
25 while ((len = bis.read(buffer, 0, bufSize)) != -1)
26 System.out.write(buffer, 0, len);
27
28 rc = p.waitFor();
29 }
30 catch (Exception e)
31 {
32 e.printStackTrace();
33 rc = -1;
34 }
35 finally
36 {
37 return rc;
38 }
39 }
40 }
41 /
Java created.
rt_test@ORA9I.WORLD> create or replace
2 function RUN_CMD(p_cmd in varchar2) return number
3 as
4 language java
5 name 'Util.RunThis(java.lang.String) return integer';
6 /
Function created.
rt_test@ORA9I.WORLD> create or replace procedure RC(p_cmd in varchar2)
2 as
3 x number;
4 begin
5 x := run_cmd(p_cmd);
6 end;
7 /
Procedure created.
rt_test@ORA9I.WORLD> variable x number;
rt_test@ORA9I.WORLD> set serveroutput on
rt_test@ORA9I.WORLD> exec dbms_java.set_output(100000);
PL/SQL procedure successfully completed.
rt_test@ORA9I.WORLD> exec :x := RUN_CMD('/usr/bin/ls /tmp');
10514.ksh
10565.sql
...
xxx.dat
xxx.dbf
zz
PL/SQL procedure successfully completed.
rt_test@ORA9I.WORLD>
A reader, March 04, 2002 - 6:05 am UTC
Any workaround on 8.1.5
Senthil, April 29, 2002 - 4:37 pm UTC
Tom-
procedure dbms_java.grant_permission is available from 8.1.6. Is there any workaround available in 8.1.5 to achieve the same functionality. I am using 8.1.5 on windows NT. It throws the following error if i try to assign permission to any user...
PLS-00302: component 'GRANT_PERMISSION' must be declared
thanks,
senthil
April 29, 2002 - 9:05 pm UTC
There is JAVASYSPRIV (a role) you can grant but beware -- it is "all powerful". The granular privilege model added in 816 and up is far superior. Make sure to lock down this account so this role cannot be abused.
I think this what I need
Adam Hapworth, May 08, 2002 - 10:36 am UTC
I am looking at making a Java-procedure like the ones you have shown to run a program on our Unix server. The question I have is will I be able to have a user on a client machine run this java-procedure from a Form(4.5 now 6 coming) and get results back from the program on the server. I have seen a number of other news group posts regarding this with no answer and thought I would ask here where the experts are.
May 08, 2002 - 12:12 pm UTC
The answer is simply "YES".
The reason, all Java stored procedures are called through a wrapper, like this:
rt_test@DEV816> create or replace
2 function RUN_CMD( p_cmd in varchar2) return number
3 as
4 language java
5 name 'Util.RunThis(java.lang.String[]) return integer';
6 /
Function created.
that maps the java types to SQL types. So, externally, it looks like PLSQL to the caller, but underneath, it is java.
Java procedure for host calls on Unix environment
Sandeep Lekhwani, June 06, 2002 - 2:02 pm UTC
Hi Tom,
Content proved to be very useful.
But, I am facing a problem.
The ksh I am calling from oracle using this utility, has some parameters. Now, some of the parameters contain the spaces. While running the ksh from unix we just put these parameters in double quotes. But, when calling from oracle, it identifies them as delimiters and hence treat as separate parameters. Is there a way that I can make it avoid the spaces which are inside double quotes. Or can I specify some other delim? Pls let me know. It's really urgent.
June 06, 2002 - 5:46 pm UTC
We are not parsing anything -- I don't understand what you mean? We are just executing a string -- passing it to the command interpreter.
There undoubtably exists a more sophisticated java api as well that lets you set an array of parameters instead of just string -- you could look that up as well.
help debugging, PLEASE :-)
George Liblick, June 19, 2002 - 2:26 pm UTC
Tom,
I cut and past your solution, then modified the procedure
names and changed the grant_permission to /usr/ucb/ps because that is what I found through the which command
on my box (/usr/bin/ps appears to be identical anyway.)
But when I execute the command, I am getting an error that
I don't know where to begin debugging...
SQL> exec cmd( 'ps -f' );
java.lang.ArrayIndexOutOfBoundsException
at MyCommand.RunThis(MYCOMMAND:14)
PL/SQL procedure successfully completed.
.. it works the same for /usr/ucb/ps ..
You have been a great help in the past - thanks - and I
hope you will help one more time.
June 19, 2002 - 9:48 pm UTC
search this question from the top for ArrayIndexOutOfBoundsException and you'll see the fix for 9i.
Thanks
George, June 20, 2002 - 12:06 pm UTC
I hate when the answer implies I didn't do my home work :-(
Both yesterday and today I searched for ArrayIndexOutOfBoundsException throughout the archives, but the search failed to return anything... I never thought the
answer would be right under my nose :-( I wonder why your site search failed to find this?
Anyway, it is working now and you have been most gracious - thanks.
June 20, 2002 - 12:15 pm UTC
partly my fault.
My index is on the q&a. Not the comments.
I have to code a function in this style:
</code>
http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:440419921146 <code>
in order to assemble the question, answer and all comments and responses into a clob and let intermedia index that! Just haven't done it yet, will do it soon (bothers me too)
that why i like oracle .. u can do almost anything
Nitin Gulati, August 21, 2002 - 9:49 pm UTC
Hi tom,
I am facing a problem of similar type.
I need to change permission in few files which are made from utl_file though oracle onli. I think this solution will help me. But when i scearch dbms_java in all objects i cannot find there. Is there anything wrong in my oracle installation. When i scearh for dbms_java in /$oracle_HOME/rdbms/admin i cant find there also so how to load this ?
But no doubt the explanation is really good
cheers,
nitin
August 22, 2002 - 8:59 am UTC
If you do not have java installed, your DBA can install it via initjvm.sql found in $ORACLE_HOME/javavm/install
great response, but...
craig, October 10, 2002 - 6:28 pm UTC
Tom -
Your examples work great, but I'm having some trouble running my particular command using your script.
I'm trying to use scp to move files from the database to another box. I can run this from the shell a-ok, but when run via your class, it returns a 1 (failure) every time. Indeed, the file does not exist in the new location when it is all said and done. Can you help me out?
Again, the following works from the shell on the db box:
/usr/bin/scp /u01/home/cnelson/flat_files/CSV2.txt cnelson@pspdwhp1:/u01/home/cnelson/CSV2.txt
Thanks again for your sage advice.
October 11, 2002 - 8:06 pm UTC
Well, you ran that script as YOU (cnelson) where as the java ran as ORACLE
different user
different environment
different everything
suggestion:
a) log in as Oracle and test this scp, make sure Oracle can run it (permissions)
b) start out with a script /tmp called "test.sh"
In there put in a call to
/usr/bin/env
and make sure the environment is OK (paths and everything else are totally differnet)
Then add the call to /usr/bin/scp in there (eg: incrementally add in things -- try to figure out where it is going awry)
Very Useful - How about returning output greater than 32K?
Greg DelVecchio, November 08, 2002 - 6:52 pm UTC
I managed to alter your example so that it returns the command line output as a varchar2. However, some of my commands output more than 32K of data. Is there a way to pass more than 32K of data from Java to PL/SQL? Could you pass the command line output as a CLOB or break it into a varray? Thanks for any suggestions you might have.
(NOTE: For others that may try this in 8.1.7. There is a bug (#1322857) that limits the string length that may be returned by a java stored function to 4K. If you write it as a java stored procedure you may pass a string up to 32K in length)
November 08, 2002 - 9:18 pm UTC
You'll have to use a CLOB - the caller could allocate a temporary clob and the java could write to it.
Problem when passing string parameters with lots of white spaces
Mahomed Suria, November 20, 2002 - 5:08 am UTC
I am running a unix script exec_cmd.sh using rc.exec as per your example. The script is simply
#!/bin/sh
$@
#finish
When a send several parameters including one that is a string with lots of white spaces , the string is being treated as several parameters rather than just one, even when I hav enclosed the string in double qoutes.
rc ('/usr/users/cdb_env/exe/exec_cmd.sh /usr/users/cdb_env/exe/
qsnd 1 triggr yrdman 1 "+000000001+000000001+000000001DC1 DL1 steve PC" ' )
When I list the parameters that exec_cmd.sh is receiving I get the following :
/usr/users/cdb_env/exe/qsnd
1
triggr
yrdman
1
"+000000001+000000001+000000001DC1
DL1
steve
PC"
It seems like the quoted string is being split into several parameters. I want the string to be a single parameter.
Can you help? I do not know what the problem is?
November 21, 2002 - 12:04 pm UTC
You'll have to read up on java -- the answer would lie there. You could use a lower level java api then the rather simple one i have here (no, I don't know the name or even if it exists)
As a workable workaround -- suggest you pass a single string for that parameter using an _ where you have whitespace and then using sed to remove it. EG:
$ cat /tmp/test.sh
#!/bin/sh
/usr/bin/echo '$1 = ' $1
X="`echo $1 | sed 's/_/ /g'`"
echo '$X = ' $X
/usr/bin/echo ---------------
and then:
rt_test@ORA817DEV.US.ORACLE.COM> exec rc('/tmp/test.sh a_b ' )
$1 = a_b
$X = a b
---------------
return code = 0 from /tmp/test.sh a_b
so, your script would use $X instead of $1 or you could just use
`echo $1 | sed s/_/ /g`
in your script where currently you just have $1
Calling OS command using Java procedure in PL/SQL generates NON-EXISTANT PROCESS on NT
Alain Labonte, December 19, 2002 - 11:48 am UTC
Hi, i use a java procedure mostly similar to this one, but when the command is terminated, a NON-EXISTANT PROCESS stays on the server (NT 4.0). Those processes seem to take some memory. So when i execute many jobs, they take a lot of memory and slow down my server. When i stop my database, they disapear, but i can't stop my database at anytime.
Do you have any idea of what might causes that?
December 19, 2002 - 12:59 pm UTC
I don't know what a "non existant process on nt" means.
need to run a script
tong siew pui, January 07, 2003 - 1:15 am UTC
The info is very useful. Many thanks.
I am able to follow the example and get the results as stated.
But what I needed is to run a unix script (with different unix commands), instead of a unix command.
I have a script 'tsp1.txt' in
/u01/home/sinvb/tong
tsp1.txt
--------
ls -la
when I run
SQL> exec rc('/u01/home/sinvb/tong/tsp1.txt');
PL/SQL procedure successfully completed.
but the files are not listed.
when I run the command
'tsp1.txt' at '/u01/home/sinvb/tong'
the files get listed.
I tried different alternative
1) modified tsp1.txt to
sh -c 'ls -la'
2) copy the file tsp1.txt to /usr/bin
and
exec rc('/usr/bin/tsp1.txt');
both show the same result
PL/SQL procedure successfully completed.
pls adv what is the pbm and what must I do.
the ultimate aim is to prepare tsp1.txt as
a unix script which contains various unix command.
thanks for your help in advance.
i also noticed that if i run
exec rc('/usr/bin/ps')
nothing is displayed.
but i got results if i run
exec rc('/usr/bin/ps -ef');
but if i execute the command 'ps',
i get something displayed.
is there a reason why ???
January 07, 2003 - 6:24 am UTC
time for you to do a little debugging eh?
did you check the permissions? can ORACLE run your script? is the r-x flag on the entire path to this file? is ls in the rarified environment these scripts run in? what is the path? did you put some
/usr/bin/echo $PATH > /tmp/$$.debug
type statements in there?
is the script getting run at all?
did you read the "great response, but... " comment above and do what I suggested there?
.......
Stephan, January 09, 2003 - 5:53 am UTC
Try to execute the following:
exec rc('/usr/bin/sh /u01/home/sinvb/tong/tsp1.txt');
Note the sh command to open a shell and your script as 'parameter'. Be sure you have execute permissions for sh (with dbms_java.grant_permission).
This should output the desired result.
January 09, 2003 - 7:27 am UTC
as I said above however -- that would be a really bad idea.
you have to give privs on sh
exec rc( '/usr/bin/sh rm -rf /u01/apps/oracle/oradata/your_sid/*' )
is as easy to execute as tsp1.txt would be! caveat emptor.
Using Java
Abdal-Rahman Agha, January 16, 2003 - 12:41 am UTC
Hi Tom,
- Sorry, I am interesting to use Java in Oracle, can you advice on a book or any good place to learn about Oracle Java quickly?
- I have Win2k, Oracle9 R2: Please, explain this output:
SQL> exec rc('E:\WINNT\command.* /c dir');
java.lang.ArrayIndexOutOfBoundsException
at Util.RunThis(Util.java:14)
PL/SQL procedure successfully completed.
January 16, 2003 - 8:32 am UTC
that error just means you got really excited -- stopped reading the article and went to play with it! read on -- ctl-f for ArrayIndexOutOfBoundsException and you'll see the cause.
you might be interested in
</code>
http://www.amazon.com/exec/obidos/ASIN/1861006020/ <code>
Is it possible to call os comand of another server
Reader, January 18, 2003 - 2:56 am UTC
Hi Tom
This is excellent piece of Code.
i have one clarification. Is it possible to call a particular command in other unix server.
Ie My oracle DB is in Unix server A
My ETL tool is running in Unix server B
I want to call the ETL Process as Commandline from Java procedure. Will it need to login into Server B. If so How to do it.
January 18, 2003 - 9:01 am UTC
if you can do it from sever A on the command line (outside of oracle), we can do it inside the database.
Solve that problem and we'll go from there. Oracle cannot bypass the OS and do magical things beyond what you've set up at the OS level.
We can use C based extprocs in 9i to do this as the extproc is allowed to run on another machine all together. but basically, you would need an agent on server b one way or another.
error on excuting java
Nikunj, February 03, 2003 - 12:20 am UTC
hi tom,
i have oracle ee 8.1.7 on windows nt 4.0 with service pack 6a. i want to execute host command from database.
so i follow ur steps as below.
SQL> CONNECT SYSTEM@BABUL
Enter password: *******
Connected.
SQL> begin
2 dbms_java.grant_permission
3 ('SCOTT',
4 'java.io.FilePermission',
5 'C:\WINNT',
6 'execute');
7
8 dbms_java.grant_permission
9 ('SCOTT',
10 'java.lang.RuntimePermission',
11 '*',
12 'writeFileDescriptor' );
13 end;
14 /
PL/SQL procedure successfully completed.
SQL> connect scott@babul
Enter password: *****
Connected.
SQL>
SQL> create or replace and compile
2 java source named "Util"
3 as
4 import java.io.*;
java source named "Util"
*
ERROR at line 2:
ORA-29536: badly formed source: Encountered "<EOF>" at line 1, column 17.
Was expecting:
";" ...
why i am geting this error.
thanks nikunj
February 03, 2003 - 7:24 am UTC
what version of sqlplus do you have.
This:
ops$tkyte@ORA817DEV> create or replace and compile
2 java source named "Util"
3 as
4 import java.io.*;
java source named "Util"
*
ERROR at line 2:
ORA-29536: badly formed source: Encountered "<EOF>" at line 1, column 17.
Was expecting:
";" ...
is what I get when I use 8.0 sqlplus which didn't understand "java source". It just sucked the code upto the first ';' and submitted it (since sqlplus didn't know back then that java source
a) existed
b) could contain ';' like plsql can
suggest you get your client software updated.
Java Permisson
Steve, February 25, 2003 - 2:36 pm UTC
Hi Tom,
I just tried the answer here but I got the following messssage. What should I do? Thanks! --steve
SQL> call testjava.run_cmd('ls') into :y;
java.security.AccessControlException: the Permission (java.io.FilePermission <<ALL FILES>> execute)
has not been granted by dbms_java.grant_permission to
SchemaProtectionDomain(SRS|PolicyTableProxy(SRS))
at java.security.AccessControlContext.checkPermission(AccessControlContext.java)
at java.security.AccessController.checkPermission(AccessController.java)
at java.lang.SecurityManager.checkPermission(SecurityManager.java)
at oracle.aurora.rdbms.SecurityManagerImpl.checkPermission(SecurityManagerImpl.java)
at java.lang.SecurityManager.checkExec(SecurityManager.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at Util.RunThis(Util:13)
Call completed.
February 25, 2003 - 8:28 pm UTC
did you use dbms_java grant permission to grant yourself the needed privs? like my example does?
Why it is not able to run java class
Umesh Nimbalkar, March 13, 2003 - 7:00 am UTC
Dear Tom,
I want to run class placed in one directory. For this i am giving permissions as follows
begin
dbms_java.grant_permission
('SALES',
'java.io.FilePermission',
'/usr/java130/jre/bin/java',
'execute');
dbms_java.grant_permission
('SALES',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
end;
/
now when i am trying to execute as below
exec rc('/usr/java130/jre/bin/java -version');
it is not giving any output. but if i run like
exec rc('/usr/java130/jre/bin/java');
it is iving output.
Pls let me know why it is not accepting parameters.
March 14, 2003 - 5:06 pm UTC
maybe the -version is writing to stderr. mine does:
$ java -version > xxx
java version "1.3.1_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_02-b02)
Java HotSpot(TM) Client VM (build 1.3.1_02-b02, mixed mode)
I only caught stdout.
Oracle Application Developer
Dawar, March 19, 2003 - 2:19 pm UTC
Is there a way to call unix command in oracle programs/ packages?
Dawar
March 19, 2003 - 3:43 pm UTC
umm, you mean like this:
rt_test@DEV816> exec rc('/usr/bin/ps -ef');
UID PID PPID C STIME TTY TIME CMD
root 0 0 0 Aug 17 ? 0:06 sched
root 1 0 0 Aug 17 ? 1:19 /etc/init -
root 2 0 0 Aug 17 ? 0:23 pageout
.....
PL/SQL procedure successfully completed.
which is the example from above???
Having small problem
Rob, April 24, 2003 - 12:39 pm UTC
I was able to run your example ps -ef with no problem.
I create a simple shell script on UNIX to copy a file rfk.scr:
cp /apps/actappl/rfk.test /apps/actappl/rfk.test2
I can run this with no problem using the Oracle account on UNIX.
When I try to run it using the Java callout nothing happens, no errors no copy.
DECLARE
t NUMBER(9);
BEGIN
t := act_dw_sys_events.run_cmd('/apps/actappl/rfk.scr');
END;
Any suggestions?
Thanks Rob
April 24, 2003 - 12:44 pm UTC
scripts can be tricky.
did you grant on it.
is is executable by the oracle software owner.
is the path to it traversable by the oracle software owner.
can the oracle software owner write to that directory.
can it read that file.
what was the return code.
look for (cnelson) on this page (had the same issue). ideas are there as well.
interesting response but do not answer to my problem
Rene Paradis, April 24, 2003 - 4:52 pm UTC
I want to execute a second perl script into the perl script called by the Java procedure like:
system("/path/perl_script.pl argv");
But
But the java grant permissions seem to allow only the first perl script to be executed and this one ends when the system command is called.
here is the granted permissions
begin
dbms_java.grant_permission
('SUPER_MAN',
'java.io.FilePermission',
'/path/first_script.pl',
'execute,read ,wrtie');
dbms_java.grant_permission
('SUPER_MAN',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
end;
/
begin
dbms_java.grant_permission
('SUPER_MAN',
'java.io.FilePermission',
'/path/second_script.pl',
'execute,read ,wrtie');
dbms_java.grant_permission
('SUPER_MAN',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
end;
/
if it is not possible to call a second perl script inside the first one, I planned to call it separatly:
declare
x number;
begin
x := run_cmd('/path/first_script.pl argv');
x := run_cmd('/path/second_script.pl argv');
end;
/
April 24, 2003 - 6:09 pm UTC
I missing your point?
if first_script.pl calls second_script.pl -- you need not grant on it (the Oracle JVM has *no clue* what first script might do, and it is allowed to do anything it wants really as far as running other commands go)
if first_script.pl doesn't call second_script.pl, but you want to -- you just need to grant on it.
So, I'm not understanding what you are saying here.
excellent
A reader, April 25, 2003 - 10:54 am UTC
did not solve my problem (first and second perl script)
Rene Paradis, April 25, 2003 - 11:48 am UTC
Hi again Tom,
here is my part of code inside the first perl script that calls the second perl script:
...
$fichier = shift @ARGV;
print("test1 tahaa/mascot/data/make_input_txt.pl $fichier\n");
#we build a txt file here
$x = system("/tahaa/mascot/data/make_input_txt.pl $fichier");
print("x value is $x\n");
...
the dbms.output would be:
test1 /seq/murin/proteo/make_input_txt.pl /tahaa/mascot/data/20030327/F006236.dat
PL/SQL procedure successfully completed.
The x value is not printed. but when I execute the command manually (/seq/murin/proteo/make_input_txt.pl /tahaa/mascot/data/20030327/F006236.dat), the script works. So it really seems that the first script cannot execute the system command, altough it does when it is executed manually. What should I do to make it work?
thank you very much for your help
April 25, 2003 - 3:37 pm UTC
this looks like a classic PERMISSION problem at the OS level.
put some debug in. remember -- as coded, this catches ONLY stdout -- you might want yet another wrapper -- a script that runs perl1 (which runs perl2) but redirects stderr to stdout so you can see it.
UNDOUBTABLY perl is pumping out an error to stderr and you just haven't seen it yet.
dk, May 07, 2003 - 6:32 pm UTC
Hi Tom,
I am a dveloper.
When I try to creat a java stored procedure in database, I met the following message, what happend ? What requirement I need
to ask DBA?
Thanks!
DLIV>create or replace and compile
2 java source named "Util"
3 as
4 import java.io.*;
java source named "Util"
*
ERROR at line 2:
ORA-29547: Java system class not available: oracle/aurora/rdbms/Compiler
May 08, 2003 - 9:33 am UTC
search for
ORA-29547
on this site
It almost works perfectly
Mark, May 15, 2003 - 10:51 am UTC
Tom,
I will appologize in advance because I think this might go a bit beyond the scope of the original question.
I modified your code to work on Windows and after some dumb mistakes on my part I can now execute commands at will from Oracle 9i stored procedures.
Thanks
There is one problem though that I have not been able to resolve yet. When I execute a batch file and that batch file then executes another program (not internal command) I get no output. It's like standard out has been redirected to the bit bucket. If I execute an internal command like 'dir' or 'set' I get the output in the stored procedure. I can also redirect that output to a file from within the batch file called from the stored procedure. But when I execute an external program, for example a "Hello World" java program or grep (windows version) to get some text, there is no output. The ERRORLEVEL indicates the program ran.
Any ideas what could be going on here?
May 15, 2003 - 5:51 pm UTC
windows isn't unix and concepts like stdin, stderr, stdout are so foriegn to it.
they do not all share the same "tty" if you will. don't know what to tell you other then use redirection and then "type" the output.
Can't get permissions to set up correctly..
Mahomed, May 16, 2003 - 1:04 pm UTC
Oracle9i Release 9.2.0.1.0 - Production
JServer Release 9.2.0.1.0 - Production
SQL> connect / as sysdba
begin
dbms_java.grant_permission
('CDB_TRAIN',
'java.io.FilePermission',
'/data4/cdb_train/exe/exec_cmd',
'execute');
dbms_java.grant_permission
('CDB_TRAIN',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor');
end;
/
PL/SQL procedure successfully completed.
exec dbms_java.grant_permission( 'CDB_TRAIN','SYS:java.io.FilePermission','/usr/cdb_train/exe/exec_cmd', 'execute' );
PL/SQL procedure successfully completed.
exec :x := pkg_utils.sp_cmd('test',3,'/data4/cdb_train/exe/db_locks');
java.security.AccessControlException: the Permission (java.io.FilePermission
/usr/cdb_train/exe/exec_cmd execute) has not been granted to CDB_TRAIN. The
PL/SQL to grant this is dbms_java.grant_permission( 'CDB_TRAIN',
'SYS:java.io.FilePermission', '/usr/c
db_train/exe/exec_cmd', 'execute' )
at java.security.AccessControlContext.checkPermission(AccessControlContext.java)
at java.security.AccessController.checkPermission(AccessController.java)
at java.lang.SecurityManager.checkPermission(SecurityManager.java)
at
oracle.aurora.rdbms.SecurityManagerImpl.checkPermission(SecurityManagerImpl.java
)
at java.lang.SecurityManager.checkExec(SecurityManager.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at MyCommand.RunThis(MyCommand.java:14)
PL/SQL procedure successfully completed.
May 16, 2003 - 5:14 pm UTC
so show us a TRUE cut and paste, nothing doctored as above.
Another compile problem...
Jack Wells, May 18, 2003 - 2:17 pm UTC
Tom,
I'm getting the following error when I try to create the Util Java source:
SQL> sho err
Errors for JAVA SOURCE Util:
LINE/COL ERROR
-------- -----------------------------------------------------------------
0/0 Util:4: Superclass object of class Util not found.
0/0 Info: 1 errors
SQL>
I get the same error on an 8.1.7.4 HP/UX instance, a Linux 9.2.0.3 instance and a 9.2.0.1 Windows instance. Running the dbms_java.grant_permission, however, works fine on all three. What is the "superclass object" of Util? Is it one of the two imports just above the Util class declaration?
May 18, 2003 - 2:52 pm UTC
hows about the entire example -- never saw that myself.
Another compile problem (full example)...
Jack Wells, May 18, 2003 - 4:26 pm UTC
Tom,
Here is the whole example:
SQL> connect sys@ncgd
Enter password: *****
Connected.
SQL> select version from v_$instance;
VERSION
-----------------
8.1.7.4.0
1 row selected.
SQL> CREATE OR REPLACE AND COMPILE
2 JAVA SOURCE NAMED "Util"
3 AS
4 import java.io.*;
5 import java.lang.*;
6
7 public class Util extends object
8 {
9 public static int runthis(string args)
10 {
11 runtime rt = runtime.getruntime();
12 int rc = -1;
13
14 try
15 {
16 process p = rt.exec(args);
17
18 int bufsize = 4096;
19 bufferedinputstream bis =
20 new bufferedinputstream(p.getinputstream(), bufsize);
21 int len;
22 byte buffer[] = new byte[bufsize];
23
24 // echo back what the program spit out
25 while ((len = bis.read(buffer, 0, bufsize)) != -1)
26 system.out.write(buffer, 0, len);
27
28 rc = p.waitfor();
29 }
30 catch (exception e)
31 {
32 e.printstacktrace();
33 rc = -1;
34 }
35 finally
36 {
37 return rc;
38 }
39 }
40 }
41 /
Warning: Java created with compilation errors.
SQL> sho err
Errors for JAVA SOURCE Util:
LINE/COL ERROR
-------- -----------------------------------------------------------------
0/0 Util:4: Superclass object of class Util not found.
0/0 Info: 1 errors
SQL>
May 18, 2003 - 6:27 pm UTC
object
should be
Object
initcap, java is case sensitive.
rt_test@DEV816> create or replace and compile
2 java source named "Util"
3 as
4 import java.io.*;
5 import java.lang.*;
6
7 public class Util extends Object
8 {
9
Duh...
Jack Wells, May 19, 2003 - 1:31 am UTC
Oh.
After correcting that faux pax, there were a few other "spelling" mistakes I needed to correct... works like a charm now!
p.s. Note to self: don't use PL/Formatter on Java code!
Got an error
A reader, May 19, 2003 - 4:20 pm UTC
I copied the same code but got an error
SQL> exec rc('/usr/bin/ps -ef');
java.lang.ArrayIndexOutOfBoundsException
at Util.RunThis(UTIL.java:14)
What is problem?
What are the pre-requisites to run this?
Emelyn, June 10, 2003 - 3:05 pm UTC
In order to run your Java program, do I need to add entries to listener.ora and tnsnames.ora or any preparation or set-up to be done?
I'm running version 8.1.5.
Thanks in advance!
June 10, 2003 - 3:12 pm UTC
just have java installed in the database.
What are the pre-requisites to run this?
Emelyn, June 10, 2003 - 6:31 pm UTC
Here's what I got when I ran sql*plus:
SQL*Plus: Release 8.0.5.0.0 - Production on Tue Jun 10 14:52:27 2003
(c) Copyright 1998 Oracle Corporation. All rights reserved.
Connected to:
Oracle8i Enterprise Edition Release 8.1.5.0.0 - Production
With the Partitioning and Java options
PL/SQL Release 8.1.5.0.0 - Production
With the phrase: With the Partitioning and Java options
Does it mean, Java is installed?
June 10, 2003 - 8:08 pm UTC
yes.
you'll have problems creating java with the 805 sqlplus client however -- sqlplus "parses" statements before submitting them. it won't recognize 'create or replace java ....' and will most likely "barf"
Some points regarding to pass parameters to your shell
Erdal, June 11, 2003 - 12:58 pm UTC
I have been using the Java Stored Procedures a lot to replace the Pro*C Codes and all the other workarounds we did in the past to execute a command on the operating system (mostly UNIX).
There's a very good article here
</code>
http://www.mountainstorm.com/publications/javazine.html <code>
It helped me a lot for passing parameters to UNIX Shell.
{"/bin/sh", "-c", "Your Command") format has no surprises when executing anything on UNIX.
June 11, 2003 - 7:13 pm UTC
unless of course, someone gives you
"rm -rf /usr/oracle/oradata"
to run. /bin/sh would not be something I would want "open" to run.
/bin/ps, sure
/bin/sh (run anything you like), not so sure I'd like that.
about username for dbms_java.grant_permission
Jianhui, June 18, 2003 - 5:06 pm UTC
The username must be uppercase or it will report user or role doesnt exist error. This may need to be improved since pl/sql is not case sensitive traditionally.
Issue with 9i
Steve, June 19, 2003 - 8:05 am UTC
Hi Tom
I've successfully run this in 8.1.7 and have put your amended code into 9.0.1.4 but get an error. Could you glance at it and tell me where I've gone wrong please?
ltop_owner@EU0084P> conn sys/eu0084psys@eu0084p as sysdba
Connected.
ltop_owner@EU0084P> ed
Wrote file afiedt.buf
1 begin
2 dbms_java.grant_permission
3 ('LTOP_OWNER',
4 'java.io.FilePermission',
5 'e:\orant_eu0084p\scripts\bandvisit.bat',
6 'execute');
7 dbms_java.grant_permission
8 ('LTOP_OWNER',
9 'java.lang.RuntimePermission',
10 '*',
11 'writeFileDescriptor' );
12* end;
ltop_owner@EU0084P> /
PL/SQL procedure successfully completed.
ltop_owner@EU0084P> conn ltop_owner/prodltop@eu0084p
Connected.
ltop_owner@EU0084P> ed
Wrote file afiedt.buf
1 create or replace and compile
2 java source named "Util"
3 as
4 import java.io.*;
5 import java.lang.*;
6 public class Util extends Object
7 {
8 public static int RunThis(String args)
9 {
10 Runtime rt = Runtime.getRuntime();
11 int rc = -1;
12 try
13 {
14 Process p = rt.exec(args);
15 int bufSize = 4096;
16 BufferedInputStream bis =
17 new BufferedInputStream(p.getInputStream(), bufSize);
18 int len;
19 byte buffer[] = new byte[bufSize];
20 // Echo back what the program spit out
21 while ((len = bis.read(buffer, 0, bufSize)) != -1)
22 System.out.write(buffer, 0, len);
23 rc = p.waitFor();
24 }
25 catch (Exception e)
26 {
27 e.printStackTrace();
28 rc = -1;
29 }
30 finally
31 {
32 return rc;
33 }
34 }
35* }
36 /
Java created.
ltop_owner@EU0084P> ed
Wrote file afiedt.buf
1 create or replace
2 function RUN_CMD(p_cmd in varchar2) return number
3 as
4 language java
5* name 'Util.RunThis(java.lang.String) return integer';
ltop_owner@EU0084P> /
Function created.
ltop_owner@EU0084P> ed
Wrote file afiedt.buf
1 create or replace procedure RC(p_cmd in varchar2)
2 as
3 x number;
4 begin
5 x := run_cmd(p_cmd);
6* end;
7 /
Procedure created.
ltop_owner@EU0084P> conn ltop_owner/prodltop@eu0084p
Connected.
ltop_owner@EU0084P> variable x number
ltop_owner@EU0084P> set serveroutput on
ltop_owner@EU0084P> exec dbms_java.set_output(100000);
PL/SQL procedure successfully completed.
ltop_owner@EU0084P> exec :x := RUN_CMD('/usr/bin/ls /tmp');
java.io.IOException: The handle is invalid.
at oracle.aurora.java.lang.OracleProcess.create(OracleProcess.java)
at oracle.aurora.java.lang.OracleProcess.construct(OracleProcess.java)
at java.lang.Runtime.execInternal(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at Util.RunThis(Util:11)
PL/SQL procedure successfully completed.
ltop_owner@EU0084P>
June 19, 2003 - 8:07 am UTC
you seem to be on windows (e:\ ...)
but you seem to be trying to use the power of unix (/usr/bin/ls...) ???
Oops....just checking you were awake!!
steve, June 19, 2003 - 8:21 am UTC
Hide my shame!!!! I'll just wait for the ground to open up and swallow me!
Yes the server is on Windoze and if I run the correct command it runs as it should. The power of cut 'n paste!!!
"The DBA formerly known as Steve."
OS Output
Jack Wells, June 21, 2003 - 2:09 am UTC
Tom,
I'm having trouble passing the OS output back in a parameter to the calling PL/SQL binding function. I'd like to do this rather than rely on the dbms_output approach. I've added the following to the function call (per your instruction in your book):
public static int RunOsCmd(java.lang.String OsCmdLine,
java.lang.String[] CmdOutput)
Now I need to get the routine to stuff its output in the "CmdOutput" parameter. How would I do this?
June 21, 2003 - 10:33 am UTC
you'll have to write a little java to concatenate the output instead of using system.out to write it "on screen" and then assign that to CmdOutput[0] before you return.
How to concatenate output
Jack Wells, June 21, 2003 - 6:26 pm UTC
Tom,
Here is my PL/SQL binding code and Java code and output from running the program. I can't seem to get the output in the return variable. As I'm not a Java dude, I suspect I'm not concatenating correctly or not handling the "buffer" variable correctly. What is the problem?
FUNCTION run_command_java (
fv_command IN VARCHAR2,
fv_output OUT VARCHAR2
)
RETURN NUMBER
AS
LANGUAGE JAVA
NAME 'NcgOSj.runOsCmd( java.lang.String,
java.lang.String[] ) return integer';
PROCEDURE run_command_java (
fv_command IN VARCHAR2,
fv_output OUT VARCHAR2
)
IS
ln_return_code NUMBER;
BEGIN
ln_return_code := run_command_java (fv_command, fv_output);
END run_command_java;
CREATE OR REPLACE AND COMPILE
JAVA SOURCE NAMED "NcgOSj"
AS
import java.io.*;
import java.lang.*;
public class NcgOSj extends Object
{
public static int runOsCmd(String OsCmdLine,
String[] CmdOutput)
{
Runtime rt = Runtime.getRuntime();
int rc = -1;
String coutput = "";
if (OsCmdLine.length() < 1) {
System.out.println("USAGE: java NcgOSj.runOsCmd \'cmd\' OutputStringVariable");
System.exit(1);
}
try
{
// The exec() method in java.lang.Runtime is overloaded and
// can be called in different forms. The following use illustrates
// the simplest form of exec() which takes a string as a parameter.
//
// Execute the command using the Runtime object variable 'rt' and
// get the process 'p' which controls this command
Process p = rt.exec(OsCmdLine);
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);
coutput = coutput + buffer;
}
// Wait for the process 'p' to finish and get the return code
// from the process
rc = p.waitFor();
}
catch (Exception e)
{
e.printStackTrace();
rc = -1;
}
finally
{
CmdOutput[0] = coutput;
return rc;
}
}
}
/
VARIABLE outpt VARCHAR2(2000)
SET serveroutput on
EXEC dbms_java.set_output(100000);
EXEC run_command_java ('/bin/ls /', :outpt);
bin
boot
dev
etc
home
initrd
lib
lost+found
misc
mnt
ncg01
ncg02
ncg03
ncg04
ncglx01
ncglx01_cp.log
ncglx01_cp.sh
ncglx01_mount.sh
nohup.out
opt
proc
root
sbin
tmp
tmpdir
usr
var
PL/SQL procedure successfully completed.
PRINT outpt
OUTPT
-----------------------------------------------------------
[B@e8955a6a
June 21, 2003 - 6:57 pm UTC
we will have to hope a java dude comes along.
Convert...
Kamal Kishore, June 22, 2003 - 1:29 pm UTC
The byte array needs to be converted to a String before assigning to the OUT variable.
The while (read...) loop needs to be changed to the following:
// Echo back what the program spit out
while ((len = bis.read(buffer, 0, bufSize)) != -1) {
System.out.write(buffer, 0, len);
ot = new String(buffer, 0, len) ;
coutput = coutput + ot ;
}
Where "ot" is a String variable declared in the program above like this:
Runtime rt = Runtime.getRuntime();
int rc = -1;
String coutput = " ";
String ot = " " ;
This seems to work when run on my system.
June 22, 2003 - 4:25 pm UTC
Thanks, appreciate that...
Works like a charm!
Jack Wells, June 22, 2003 - 4:48 pm UTC
Thanks Kamal! Made those changes and it works just as expected.
Tell me, do you know how I could just convert the byte array variable "buffer" to a string inline instead of declaring the new variable "ot"? Something like:
// capture the output in a string variable
while ((len = bis.read(buffer, 0, bufSize)) != -1) {
coutput = coutput + toString (buffer, 0, len);
}
Wouldn't this use up less memory than allocating "new" memory for each iteration for the "ot" variable?
Hangs on sendmail
Jack Wells, June 23, 2003 - 8:44 pm UTC
Tom,
Do you have any idea why the program above would hang on a call to sendmail? As long as I have done the dbms_java.grant_permission, the program works fine for /bin/ls, /bin/rm, etc., but when I issue the following command from SQL*Plus, it just hangs:
EXEC run_command_java (/usr/sbin/sendmail jwells@nichegroup.com < /home/oracle/smtest.txt', :outpt);
The server is on Red Hat Linux AS 2.1 and 9.2 of the database. Issuing the command line as oracle at the Unix prompt works fine. Does it work on your Linux box?
June 24, 2003 - 7:41 am UTC
sendmail must be waiting for you to type something in. If you goto the OS and kill it, and it returns, that is what is happening.
write a script, call the script perhaps.
(or heck, just use UTL_SMTP eh?)
------------------------------------------------
Oh I see it, search for
you would need to run a SHELL that understands...
on this page. you sent a SHELL command (redirect). you are thinking "oh, anything that runs in shell, runs here", but it doesn't. redirection is a "shell thing"
Yong, June 24, 2003 - 4:39 pm UTC
Jack,
You cannot pass more than one parameters in this case. As tom suggested: write a script and run the script. You can use pl/sql to write a script and change run mode and call the script.
BTW, why not use pl/sql send mail with attachemet?
You were right
Jack Wells, July 07, 2003 - 12:31 pm UTC
Tom,
You were right, it was the "<" redirection... a shell thing. In my zeal to ensure only granular permissions were issued, I had avoided giving execute permission on /usr/sh. When I did, though, it worked fine. Now, the only thing that bothers me is this execute priv on /usr/sh...
July 07, 2003 - 1:25 pm UTC
so -- write a SCRIPT that you invoke that does the redirection.
"Java procedure for host calls on Unix environment"
Raja, August 11, 2003 - 12:58 pm UTC
Hi Tom,
We are looking to call a unix shell script from Oracle after an update/insert/delete happens on a table in the database. The above solution looks kind of neat, however, just wondering whether the procedure RC above could be called from a database trigger and made to execute a shell script (lets say test.sh) OR do you have any other suggestions which might help? We are using Oracle version 8.1.7
Thanks in advance!
Raja
August 11, 2003 - 2:11 pm UTC
lets back up a second.
what exactly would this shell script do? this sounds like a fairly "bad idea" for many reasons. Once I know what the script does, I'll give you a "for example"
"Java procedure for host calls on Unix environment"
Raja, August 11, 2003 - 5:14 pm UTC
Hi Tom,
In simple words, what we are trying to do here is just notify the java webserver that for example an update has occured, based on which it will initiate other necessary actions on its side on the webserver.
Actually, I do not code java. Our java developers just gave me an idea of what they want (for example to be able to execute host calls - shell scripts from Oracle which will notify the webserver for either executing something on the webserver with respect to the database update event on a table or maybe run shell script which could FTP some files or other information for each updated)
Let me know if this is enough or need more details.
Regards,
Raja
August 11, 2003 - 6:54 pm UTC
well, the update hasn't really happened -- NOT until you commit anyhow.
what about this:
update t set x = 5; -- update 1,000,000 records
ROLLBACK;
whoops -- so sorry, I just ran 1,000,000 sh scripts to notify someone about
a) an even they cannot see (since I did not commit, they can never have seen the updated data)
b) that didn't really happen.
Another interesting on -- read this article:
</code>
http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:11504247549852 <code>
to see an update that updates 4 rows BUT fires the row trigger 6 times! what about that?
You want to read about AQ (advanced queues) I believe and they want to use JMS to be notified about events.
It is nice and transactional. they'll only get notified of REAL ACTUAL committed events.
"Java procedure for host calls on Unix environment"
Raja, August 12, 2003 - 11:44 am UTC
Hi Tom,
Thanks a lot for a prompt reply. This is certainly helping. Actually, just wanted to know if JMS supported in Oralce 8.1.7 as, I just happened to go to metalink (let me know if I am looking at the right article).....
</code>
http://metalink.oracle.com/metalink/plsql/ml2_documents.showDocument?p_database_id=NOT&p_id=232301.1 <code>
and it mentions.....
The following requirements need to be satisfied when using JMS-AQ:
OC4J 9.0.3.0.0
Supported RDBMS version
Oracle9i Database 9.0.1.4 (Patch: 2517300)
Oracle9i Database 9.2.0.2 (Patch: 2632931)
For further information, see:
Note:230372.1
Send JMS Messages to OJMS Queue Fails with PLS-00306
You,ve been very helpful!
Regards,
Raja
August 12, 2003 - 12:00 pm UTC
is there any security issue
please help, August 26, 2003 - 1:41 pm UTC
Hi Tom,
Thanks for this nice solution, currently I am using it to call sqlldr to load a file into a table from plsql, since it will run sqlldr as user oracle, my boss worrys about any possible security hole here, please give me some your comments
Thanks
August 27, 2003 - 7:45 am UTC
what is your boss worried about exactly?
using java with very very specific grants like this (eg: this user is allowed to run /home/oracle/bin/sqlldr and nothing else) is much more secure then the other methods of:
o using an extproc. that can run any code the user running the extproc listener can run
o using "java_sys_priv" or some other broad ranging privs.
if you have a specific concern, we can address that.
Trigger again
Warren, September 16, 2003 - 2:30 pm UTC
Tom,
I noticed that you had put the person off who asked about using triggers, but I have a similar question. OK, I have a third party app that is inserting or updating into a table, tableA. I would like to set up a trigger on these actions such that it will call a batch file (say devtest.bat, sorry I had to use Windows for these guys). Can I use your method to pass a column name (call it Project_Name) from tableA to the devtest.bat file?
The insert/update is automatically committed by the application when the click on the OK button. No rollback opportunity, and no other ad-hoc application (i.e. sqlplus) access to the database.
I have your method working calling the devtest.bat file directly, but can't get a trigger working for this.
Thanks!
September 16, 2003 - 6:11 pm UTC
tell you want -- read this:
</code>
http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:11504247549852 <code>
and see if you REALLY want to call a bat file from a trigger. pretend where I use a sequence - you called your bat file. think about the ramifications....
you want to use a stored procedure, invoked by dbms_job, AFTER the transaction commits. It is the only transactional method that works.
yes, you can pass a parameter to a script.
but I don't have a windows machine anywhere to play with to test for you.
you might have to invoke "cmd /c ....." in order to get it to go.
but that means you need to be able to run "cmd.exe" which means you can run ANYTHING. (not good)
Works nicely
Mike, December 02, 2003 - 12:42 pm UTC
Tom's code works well. Question: is it possible to expand the solution to also populate the DIR_LIST table with file attributes such as size and last-mod date? If so, any code snippets to share?
Return value into a variable
Highlander, January 07, 2004 - 1:27 pm UTC
Tom,
Can you post an axample of the "Util" java that will return the output to a variable or lob instead of dbms_output.
Thank you.
January 07, 2004 - 6:31 pm UTC
on the road, in a car right now (not conducive to massive coding :)
ask some other time when I'm taking questions (or search the site for java examples that show how to return strings and other such things -- they are out there, I had them all in my book "Expert one on one Oracle" as well)
AUTHID CURRENT_USER - privileges problem
Andriy Terletskyy, January 08, 2004 - 10:20 am UTC
Hi Tom,
I have two Questions:
1. I defined the java source and wrapper function RUN_CMD with invoker-rights AUTHID CURRENT_USER in SCHEMA1 (GLOBAL) and granted the execute right on RUN_CMD to SCHEMA2 (WP).
After that I granted the execute and writeFileDescriptor permission with DBMS_JAVA.GRANT_PERMISSION to user WP (SCHEMA2).
If I trying to execute this functiom with user WP (SCHEMA2) :
...
GLOBAL.run_cmd('/oracle/u01/app/oracle/admin/BBSE/appscripts/ls.sh')
...
FEHLER in Zeile 1:
ORA-29532: Java call terminated by uncaught Java exception:
java.security.AccessControlException: the Permission (java.io.FilePermission
/oracle/u01/app/oracle/admin/BBSE/appscripts/ls.sh execute) has not been
granted to GLOBAL. The PL/SQL to grant this is dbms_java.grant_permission(
'GLOBAL', 'SYS:java.io.FilePermission',
'/oracle/u01/app/oracle/admin/BBSE/appscripts/ls.sh', 'execute' )
ORA-06512: at "GLOBAL.RUN_CMD", line 0
ORA-06512: at line 5
What's wrong?
2. How I can write the wrapper function based on Java-class another user?
WP@BBSE> create or replace
2 function RUN_CMD( p_cmd in varchar2) return number
3 as
4 language java
5 name 'GLOBAL:Util.RunThis(java.lang.String[]) return integer';
6 /
Warnung: Funktion wurde mit Kompilierungsfehlern erstellt.
WP@BBSE> show error
Fehler bei FUNCTION RUN_CMD:
LINE/COL ERROR
-------- -----------------------------------------------------------------
0/0 PL/SQL: Compilation unit analysis terminated
4/3 PLS-00311: the declaration of
"GLOBAL:Util.RunThis(java.lang.String[]) return integer" is
incomplete or malformed
Thanks
January 08, 2004 - 3:18 pm UTC
1) worked for me. See full example below (shows that the invoker OPS$TKYTE needs the priv, not the owner RT_TEST)
2) this works:
ops$tkyte@ORA920PC> create synonym "Util" for rt_test."Util"
2 /
Synonym created.
ops$tkyte@ORA920PC>
ops$tkyte@ORA920PC> create or replace
2 function RUN_CMD(p_cmd in varchar2) return number
3 as
4 language java
5 name 'Util.RunThis(java.lang.String) return integer';
6 /
Function created.
And in this case -- OPS$TKYTE is the true invoker and OPS$TKYTE would need execute on ls (not RT_TEST)
ops$tkyte@ORA920PC> begin
2 dbms_java.grant_permission
3 ('RT_TEST',
4 'java.io.FilePermission',
5 '/bin/ls',
6 'execute');
7
8 dbms_java.grant_permission
9 ('RT_TEST',
10 'java.lang.RuntimePermission',
11 '*',
12 'writeFileDescriptor' );
13 end;
14 /
PL/SQL procedure successfully completed.
ops$tkyte@ORA920PC>
ops$tkyte@ORA920PC> @connect rt_test/rt_test
ops$tkyte@ORA920PC> set termout off
rt_test@ORA920PC> REM GET afiedt.buf NOLIST
rt_test@ORA920PC> set termout on
rt_test@ORA920PC>
rt_test@ORA920PC> create or replace and compile
2 java source named "Util"
3 as
4 import java.io.*;
5 import java.lang.*;
6
7 public class Util extends Object
8 {
9 public static int RunThis(String args)
10 {
11 Runtime rt = Runtime.getRuntime();
12 int rc = -1;
13
14 try
15 {
16 Process p = rt.exec(args);
17
18 int bufSize = 4096;
19 BufferedInputStream bis =
20 new BufferedInputStream(p.getInputStream(), bufSize);
21 int len;
22 byte buffer[] = new byte[bufSize];
23
24 // Echo back what the program spit out
25 while ((len = bis.read(buffer, 0, bufSize)) != -1)
26 System.out.write(buffer, 0, len);
27
28 rc = p.waitFor();
29 }
30 catch (Exception e)
31 {
32 e.printStackTrace();
33 rc = -1;
34 }
35 finally
36 {
37 return rc;
38 }
39 }
40 }
41 /
Java created.
rt_test@ORA920PC> grant execute on "Util" to public
2 /
Grant succeeded.
rt_test@ORA920PC>
rt_test@ORA920PC> create or replace
2 function RUN_CMD(p_cmd in varchar2) return number
3 authid current_user
4 as
5 language java
6 name 'Util.RunThis(java.lang.String) return integer';
7 /
Function created.
rt_test@ORA920PC> show errors
No errors.
rt_test@ORA920PC>
rt_test@ORA920PC> create or replace procedure RC(p_cmd in varchar2)
2 authid current_user
3 as
4 x number;
5 begin
6 x := run_cmd(p_cmd);
7 end;
8 /
Procedure created.
rt_test@ORA920PC> grant execute on rc to public
2 /
Grant succeeded.
rt_test@ORA920PC>
rt_test@ORA920PC> variable x number;
rt_test@ORA920PC> set serveroutput on
rt_test@ORA920PC> exec dbms_java.set_output(100000);
PL/SQL procedure successfully completed.
rt_test@ORA920PC>
rt_test@ORA920PC>
rt_test@ORA920PC> exec :x := RUN_CMD('/bin/ls /tmp');
afiedt.buf
BEQ2113
DCE2113
DEC2113
foo.dat
hostname.txt
ISPX2113
ITCP2113
kde-tkyte
ksocket-tkyte
log
LU622113
net2113
NMP2113
nscopy.tmp
nsmail-1.tmp
nsmail-2.tmp
nsmail-3.tmp
nsmail-4.tmp
nsmail-5.tmp
nsmail.eml
nsmail.html
nsmail.tmp
orbit-tkyte
RAW2113
SPX2113
ssh-XXDMz0hl
TCP2113
TCPS2113
US2113
VI2113
PL/SQL procedure successfully completed.
rt_test@ORA920PC>
rt_test@ORA920PC> @connect /
rt_test@ORA920PC> set termout off
ops$tkyte@ORA920PC> REM GET afiedt.buf NOLIST
ops$tkyte@ORA920PC> set termout on
ops$tkyte@ORA920PC>
ops$tkyte@ORA920PC>
ops$tkyte@ORA920PC> create synonym "Util" for rt_test."Util"
2 /
Synonym created.
ops$tkyte@ORA920PC>
ops$tkyte@ORA920PC> create or replace
2 function RUN_CMD(p_cmd in varchar2) return number
3 as
4 language java
5 name 'Util.RunThis(java.lang.String) return integer';
6 /
Function created.
ops$tkyte@ORA920PC> show errors
No errors.
ops$tkyte@ORA920PC>
ops$tkyte@ORA920PC> create or replace procedure RC(p_cmd in varchar2)
2 as
3 x number;
4 begin
5 x := run_cmd(p_cmd);
6 end;
7 /
Procedure created.
ops$tkyte@ORA920PC>
ops$tkyte@ORA920PC>
ops$tkyte@ORA920PC> variable x number;
ops$tkyte@ORA920PC> set serveroutput on
ops$tkyte@ORA920PC> exec dbms_java.set_output(100000);
PL/SQL procedure successfully completed.
ops$tkyte@ORA920PC>
ops$tkyte@ORA920PC>
ops$tkyte@ORA920PC> exec :x := RUN_CMD('/bin/ls /tmp');
java.security.AccessControlException: the Permission (java.io.FilePermission /bin/ls execute) has not been granted to OPS$TKYTE.
The PL/SQL to grant this is dbms_java.grant_permission( 'OPS$TKYTE', 'SYS:java.io.FilePermission', '/bin/ls', 'execute' )
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:283)
at java.security.AccessController.checkPermission(AccessController.java:399)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:545)
at oracle.aurora.rdbms.SecurityManagerImpl.checkPermission(SecurityManagerImpl.java:267)
at java.lang.SecurityManager.checkExec(SecurityManager.java:800)
at java.lang.Runtime.exec(Runtime.java:548)
at java.lang.Runtime.exec(Runtime.java:418)
at java.lang.Runtime.exec(Runtime.java:361)
at java.lang.Runtime.exec(Runtime.java:325)
at Util.RunThis(Util.java:13)
PL/SQL procedure successfully completed.
ops$tkyte@ORA920PC> exec :x := rt_test.RUN_CMD('/bin/ls /tmp');
java.security.AccessControlException: the Permission (java.io.FilePermission /bin/ls execute) has not been granted to OPS$TKYTE.
The PL/SQL to grant this is dbms_java.grant_permission( 'OPS$TKYTE', 'SYS:java.io.FilePermission', '/bin/ls', 'execute' )
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:283)
at java.security.AccessController.checkPermission(AccessController.java:399)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:545)
at oracle.aurora.rdbms.SecurityManagerImpl.checkPermission(SecurityManagerImpl.java:267)
at java.lang.SecurityManager.checkExec(SecurityManager.java:800)
at java.lang.Runtime.exec(Runtime.java:548)
at java.lang.Runtime.exec(Runtime.java:418)
at java.lang.Runtime.exec(Runtime.java:361)
at java.lang.Runtime.exec(Runtime.java:325)
at Util.RunThis(Util.java:13)
PL/SQL procedure successfully completed.
ops$tkyte@ORA920PC>
ops$tkyte@ORA920PC>
Thanks for the question regarding "Java procedure for host calls on Unix environment", version 8.1.6
fakhri, January 08, 2004 - 11:36 am UTC
hi tom,
i applied this script and i have error message :
SQL> ed
Wrote file afiedt.buf
1 begin
2 dbms_java.grant_permission
3 ('scott',
4 'java.io.FilePermission',
5 '/usr/bin/ps',
6 'execute');
7 dbms_java.grant_permission
8 ('scott',
9 'java.lang.RuntimePermission',
10 '*',
11 'writeFileDescriptor' );
12* end;
SQL> /
begin
*
ERROR at line 1:
ORA-29532: appel Java arrêté par une exception Java non interceptée :
oracle.aurora.vm.IdNotFoundException: scott is not a user or role
ORA-06512: à "SYS.DBMS_JAVA", ligne 0
ORA-06512: à ligne 2
can you help me
thanks
January 08, 2004 - 3:18 pm UTC
'scott' isn't a user
'SCOTT' probably is.
AUTHID CURRENT_USER - privileges problem
Andriy Terletskyy, January 09, 2004 - 7:12 am UTC
Hi Tom,
my two Guestions in not answered:
1. It is well that I can see the invoker need the priv. But if I give the priv to invoker and revoke that from owner - i see that:
ORA-29532: Java call terminated by uncaught Java exception:
java.security.AccessControlException: the Permission (java.io.FilePermission
/oracle/u01/app/oracle/admin/BBSE/appscripts/ls.sh execute) has not been
granted to GLOBAL.
The Permission of this script must be granted to the OWNER too? That is wrong.
2. Wrapper function based on Java-class another user.
That work, if java class is not in package, but need also owner execute privs(see 1.)
But, if I put the class in package, that dosn't work:
WP@BBSE> @conn global@bbse
Kennwort eingeben: *****
GLOBAL@BBSE> create or replace and compile java source named util as
2 package de.berenbergbank.global.tools;
3
4 import java.io.BufferedReader;
5 import java.io.BufferedInputStream;
6 import java.io.InputStream;
7 import java.io.InputStreamReader;
8 import java.io.IOException;
9
10 import java.util.Collections;
11 import java.util.LinkedList;
12 import java.util.List;
13
14
15 /**
16 * Created by IntelliJ IDEA.
17 * User: Terletskyy
18 * Date: 06.01.2004
19 * Time: 13:26:35
20 * To change this template use Options | File Templates.
21 */
22 public class Util {
23
24 public static String run_cmd(String command) throws Exception
25 {
26 StringBuffer myBuffer = new StringBuffer();
27 Process p = Runtime.getRuntime().exec(command);
28 int out;
29
30 int bufSize = 4096;
31 BufferedInputStream bis = new BufferedInputStream(p.getInputStream(), bufSize);
32 byte buffer[] = new byte[bufSize];
33 int len;
34
35 // Echo back what the program spit out
36 while ( (len = bis.read(buffer, 0, bufSize)) != -1) {
37 myBuffer.append(new String(buffer, 0, len));
38 }
39
40 if ((out=p.waitFor()) != 0 ){
41 throw new Exception("Error: "+out);
42 }
43
44 return myBuffer.toString();
45 }
46
47 }
48 /
Java wurde erstellt.
GLOBAL@BBSE> GRANT EXECUTE ON GLOBAL."de/berenbergbank/global/tools/Util" TO PUBLIC;
Benutzerzugriff (Grant) wurde erteilt.
WP@BBSE> create synonym "de/berenbergbank/global/tools/Util" for GLOBAL."de/berenbergbank/global/tools/Util"
2 /
Synonym wurde angelegt.
WP@BBSE> CREATE OR REPLACE FUNCTION RUN_CMD (in_command IN VARCHAR2) RETURN VARCHAR2
2 AS LANGUAGE JAVA NAME 'de.berenbergbank.global.tools.Util.run(java.lang.String) return java.lang.String';
3 /
Funktion wurde erstellt.
WP@BBSE> variable x Varchar2(4000);
WP@BBSE> set serveroutput on
WP@BBSE> exec dbms_java.set_output(100000);
PL/SQL-Prozedur wurde erfolgreich abgeschlossen.
WP@BBSE> exec :x := RUN_CMD ('/oracle/u01/app/oracle/admin/BBSE/appscripts/ls.sh');
java.lang.NoSuchMethodException: No applicable method found
at
oracle.aurora.util.JRIExtensions.getMaximallySpecificMethod(JRIExtensions.java)
at
oracle.aurora.util.JRIExtensions.getMaximallySpecificMethod(JRIExtensions.java)
BEGIN :x := RUN_CMD ('/oracle/u01/app/oracle/admin/BBSE/appscripts/ls.sh'); END;
*
FEHLER in Zeile 1:
ORA-29531: no method run in class de/berenbergbank/global/tools/Util
ORA-06512: at "WP.RUN_CMD", line 0
ORA-06512: at line 1
Thanks,
Andriy
AUTHID CURRENT_USER - privileges problem
Andriy Terlerskyy, January 09, 2004 - 7:32 am UTC
Sorry it must be
WP@BBSE> CREATE OR REPLACE FUNCTION RUN_CMD (in_command IN VARCHAR2) RETURN VARCHAR2
2 AS LANGUAGE JAVA NAME 'de.berenbergbank.global.tools.Util.run_cmd(java.lang.String) return java.lang.String';
3 /
Funktion wurde erstellt.
WP@BBSE> show error
Keine Fehler.
WP@BBSE> variable x Varchar2(4000);
WP@BBSE> set serveroutput on
WP@BBSE> exec dbms_java.set_output(100000);
PL/SQL-Prozedur wurde erfolgreich abgeschlossen.
WP@BBSE> exec :x := RUN_CMD('/oracle/u01/app/oracle/admin/BBSE/appscripts/ls.sh');
java.security.AccessControlException: the Permission (java.io.FilePermission
/oracle/u01/app/oracle/admin/BBSE/appscripts/ls.sh execute) has not been granted
to GLOBAL. The PL/SQL to grant this is dbms_java.grant_permission( 'GLOBAL',
'SYS:java.io.FilePer
mission', '/oracle/u01/app/oracle/admin/BBSE/appscripts/ls.sh', 'execute' )
at java.security.AccessControlContext.checkPermission(AccessControlContext.java)
at java.security.AccessController.checkPermission(AccessController.java)
at java.lang.SecurityManager.checkPermission(SecurityManager.java)
at
oracle.aurora.rdbms.SecurityManagerImpl.checkPermission(SecurityManagerImpl.java
:267)
at java.lang.SecurityManager.checkExec(SecurityManager.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at de.berenbergbank.global.tools.Util.run_cmd(UTIL.java:26)
BEGIN :x := RUN_CMD('/oracle/u01/app/oracle/admin/BBSE/appscripts/ls.sh'); END;
*
FEHLER in Zeile 1:
ORA-29532: Java call terminated by uncaught Java exception:
java.security.AccessControlException: the Permission (java.io.FilePermission
/oracle/u01/app/oracle/admin/BBSE/appscripts/ls.sh execute) has not been
granted to GLOBAL. The PL/SQL to grant this is dbms_java.grant_permission(
'GLOBAL', 'SYS:java.io.FilePermission',
'/oracle/u01/app/oracle/admin/BBSE/appscripts/ls.sh', 'execute' )
ORA-06512: at "WP.RUN_CMD", line 0
ORA-06512: at line 1
January 09, 2004 - 8:42 am UTC
yes, it appears that both need the grant -- if you feel this is "a bug", please open a tar with support -- I cannot change the code.
Java procedure for host calls on Unix environment
fakhri, January 09, 2004 - 9:15 am UTC
hi tom,
thanks for your help, all the procedures are succefull, but when I execute :
SQL> exec rc('/usr/bin/ps -ef');
java.lang.ArrayIndexOutOfBoundsException
at Util.RunThis(Util.java:11)
PL/SQL procedure successfully completed.
I have Oracle 9i database.
thx for you help.
fakhri
January 09, 2004 - 9:24 am UTC
and read the entire page........ ctl-f for arrayindexoutofbounds
win-2003
RR, January 09, 2004 - 10:33 am UTC
In redhat linux AS 2.1 with oracle 9i-2 your code worked fine.But while I am trying the following in win-2003 with oracle 9i-2 its giving the following error. Please help.
SQL> begin
2 dbms_java.grant_permission
3 ('DEVEL',
4 'java.io.FilePermission',
5 'c:\oracle\backup\abc.bat,
6 'execute');
7 end;
8 /
begin
*
ERROR at line 1:
ORA-04021: timeout occurred while waiting to lock object
SYS.JAVA$POLICY$SHARED$0000001d
ORA-06512: at "SYS.DBMS_JAVA", line 0
ORA-06512: at line 2
RE: Win 2003
Mark A. Williams, January 09, 2004 - 10:54 am UTC
'c:\oracle\backup\abc.bat
Is missing the closing tick - is that correct? Just an observation...
- Mark
rr, January 09, 2004 - 11:05 am UTC
file is present.It just hangs & giving the following error.
Same thing is happening with '*' too.
SQL> begin
2 dbms_java.grant_permission
3 ('DEVEL',
4 'java.io.FilePermission',
5 'c:\oracle\backup\*,
6 'execute');
7 end;
8 /
begin
*
ERROR at line 1:
ORA-04021: timeout occurred while waiting to lock object
SYS.JAVA$POLICY$SHARED$0000001d
ORA-06512: at "SYS.DBMS_JAVA", line 0
ORA-06512: at line 2
rr, January 09, 2004 - 11:09 am UTC
closing tick ' is present in the actual code. I just made a typo after pasting it here.thanks!
Line 5
Mark A. Williams, January 09, 2004 - 11:13 am UTC
Is line 5 correct?
'c:\oracle\backup\abc.bat,
It looks like it is missing the closing tick:
i.e., 'c:\oracle\backup\abc.bat',
Or is it just getting dropped in the copy and paste?
- Mark
A reader, January 09, 2004 - 11:37 am UTC
AS its my test database , I just shutdown & restarted the database & everything seems to be normal now. Thanks!
A reader, January 09, 2004 - 12:13 pm UTC
The Beauty of Windows shutdown and restart, everything works fine.
:-))))))
Only as 'oracle' o/s user?
Robert, January 21, 2004 - 3:10 pm UTC
Tom,
Is there any way to run this so that the o/s command is run as another user besides the 'oracle' user?
We want to implement this to run users' application scripts, but would like to limit potential security risks of users' scripts running as 'oracle'.
Thanks,
Robert.
January 21, 2004 - 3:30 pm UTC
using a C based external procedure and a listener running "as that other user", yes.
Using Java -- no.
UnsatisfiedLinkError
Janick Reynders, January 27, 2004 - 10:17 am UTC
Hi Tom,
A few months ago I tried to run a program from within Oracle using the procedure you described here,
(Actually it was a shell script) and it worked great! But just recently I tried to do the same thing on another machine, and now I get an exception:
java.lang.UnsatisfiedLinkError
at oracle.aurora.java.lang.OracleProcess.create(OracleProcess.java)
at oracle.aurora.java.lang.OracleProcess.construct(OracleProcess.java)
at java.lang.Runtime.execInternal(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at UsBblLoadingWrapper.load(UsBblLoadingWrapper:13)
Until now I have not been able to find the problem. Any ideas what could be going wrong?
Thanks,
Janick
this is the setup:
------------------
Oracle9i
- The permissions:
dbms_java.grant_permission('AMICUS', 'java.io.FilePermission', '/home/ami35/bin/loading_script.sh', 'execute');
dbms_java.grant_permission('AMICUS', 'java.lang.RuntimePermission', '*', 'writeFileDescriptor');
- The class:
create or replace and compile
java source named "UsBblLoadingWrapper"
as
import java.io.*;
import java.lang.*;
public class UsBblLoadingWrapper extends Object {
public static int load() {
Runtime rt = Runtime.getRuntime();
int rc = -1;
System.out.println("\n\n ---START--- \n\n");
try {
Process p = rt.exec("/home/ami35/bin/loading_script.sh");
int bufSize = 4096;
BufferedInputStream bis = new BufferedInputStream(p.getInputStream(), bufSize);
int len;
byte buffer[] = new byte[bufSize];
System.out.println("\n\n--stdout--\n");
// Echo back what the program spit out
while ((len = bis.read(buffer, 0, bufSize)) != -1) {
System.out.write(buffer, 0, len);
}
BufferedInputStream errbis = new BufferedInputStream(p.getErrorStream(), bufSize);
System.out.println("\n\n--stderr--\n");
while ((len = errbis.read(buffer, 0, bufSize)) != -1) {
System.out.write(buffer, 0, len);
}
rc = p.waitFor();
}
catch (Throwable e) {
e.printStackTrace();
rc = -1;
}
finally {
return rc;
}
}
}
/
- the function:
create or replace
function TEST_EXTERNAL_PROGRAM return number
as
language java
name 'UsBblLoadingWrapper.load() return integer';
/
- the script:
#!/bin/sh
echo "test"
- the call:
SQL> set serveroutput on size 1000000
exec dbms_java.set_output(1000000)
DECLARE
rc NUMBER;
BEGIN
rc := TEST_EXTERNAL_PROGRAM();
DBMS_OUTPUT.PUT_LINE('function returncode ' || rc);
END;
/SQL>
PL/SQL procedure successfully completed.
SQL> 2 3 4 5 6 7
---START---
java.lang.UnsatisfiedLinkError
at oracle.aurora.java.lang.OracleProcess.create(OracleProcess.java)
at oracle.aurora.java.lang.OracleProcess.construct(OracleProcess.java)
at java.lang.Runtime.execInternal(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at UsBblLoadingWrapper.load(UsBblLoadingWrapper:13)
function returncode -1
PL/SQL procedure successfully completed.
SQL>
January 27, 2004 - 10:43 am UTC
if you are on version 9013 or 9014, contact support and ask them to peek at bug 2598380
Sarada Priya, February 16, 2004 - 6:44 am UTC
Hi Tom,
I found this very useful, but I have a question to ask. I have a requirement wherein the Database Server, 9iAS server & Reports Server(We put all the reports output files in this after the nightly batch jobs) all in a networked environment and the Client system is web-enabled Forms9i forms. We need to build an interface wherein the user needs to see all the files available under a designated folder in the Reports Server and should be allowed to print the same. We are perplexed how to get the List of files from the Reports server. The above problem(for which you have answered) deals with the DB server itself, but this one???? Any idea? Please send in.
Thanks and Regards
Sarada Priya
February 16, 2004 - 7:44 am UTC
sorry, I don't work with reports but it seems to me that "mount" is the answer? just attach a network drive and go at it -- whatever client you have would read the directory.
How can we diagnose problems?
Ben, February 19, 2004 - 12:14 am UTC
Tom,
We've successfully implemented this on one database, and now I'm trying to implement it on a new one, but it seems the thing doesn't work. Is there an error log somewhere that would show me what went wrong?
Here's the code for the procedure that I implemented:
create or replace and compile java source named "Util" as
import java.io.*;
import java.lang.*;
public class Util extends Object {
public static int RunThis(String[] args) {
Runtime rt = Runtime.getRuntime();
int rc = -1;
try {
Process p = rt.exec(args[0]);
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;
}
}
}
/
create or replace
function RUN_CMD( p_cmd in varchar2) return number
as
language java
name 'Util.RunThis(java.lang.String[]) return integer';
/
As the SYS user, I granted the following privileges:
begin
dbms_java.grant_permission
('ROCQ',
'java.io.FilePermission',
'/tahiti/bin/test.pl',
'execute');
dbms_java.grant_permission
('ROCQ',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
end;
/
The procedure that executes the system call:
CREATE OR REPLACE PROCEDURE rocq.test_runcmd IS
resultat_rp NUMBER;
BEGIN
dbms_output.put_line('Beginning.');
resultat_rp := RUN_CMD('perl /tahiti/bin/test.pl');
dbms_output.put_line(resultat_rp);
dbms_output.put_line('Ending.');
END;
/
show errors;
And the script that is called:
#!/usr/bin/perl -w
system "echo allo >allo";
Finally, the execution:
SQL> @ test_runcmd.pls
Procedure created.
No errors.
SQL> exec test_runcmd
Beginning.
-1
Ending.
PL/SQL procedure successfully completed.
Any ideas?
Thanks for your help!
February 19, 2004 - 10:31 am UTC
you granted execute on the script.
you cannot run "perl", no grant on "perl"
if you do this:
set serveroutput on size 1000000
exec dbms_java.set_output(1000000)
you should see the java output "on screen"
Ben, February 19, 2004 - 11:04 am UTC
Just tried these grants:
begin
dbms_java.grant_permission
('ROCQ',
'java.io.FilePermission',
'perl',
'execute');
dbms_java.grant_permission
('ROCQ',
'java.io.FilePermission',
'/usr/bin/perl',
'execute');
dbms_java.grant_permission
('ROCQ',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
end;
/
But the host call still doesn't work:
SQL> set serveroutput on size 1000000
exec dbms_java.set_output(1000000)
SQL>
PL/SQL procedure successfully completed.
SQL> exec test_runcmd
Beginning.
java.lang.ArrayIndexOutOfBoundsException
at Util.RunThis(Util:8)
-1
Ending.
PL/SQL procedure successfully completed.
February 19, 2004 - 11:34 am UTC
Permissions
Ben, February 19, 2004 - 12:21 pm UTC
Just did as you suggested, but now I'm running into a classic Permissions problem.
SQL> begin
2 dbms_java.grant_permission
('ROCQ',
'SYS:java.io.FilePermission',
'perl',
'execute');
dbms_java.grant_permission
('ROCQ',
'SYS:java.io.FilePermission',
'/usr/bin/perl',
'execute');
dbms_java.grant_permission
('ROCQ',
'SYS:java.io.FilePermission',
3 4 5 6 7 '/tahiti/bin/test.pl',
'execute');
dbms_java.grant_permission
('ROCQ',
'SYS:java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
end;
/
PL/SQL procedure successfully completed.
SQL>
SQL> exec test_runcmd
Beginning.
java.security.AccessControlException: the Permission (java.io.FilePermission
<<ALL FILES>> execute) has not been granted to ROCQ. The PL/SQL to grant this is
dbms_java.grant_permission( 'ROCQ', 'SYS:java.io.FilePermission', '<<ALL
FILES>>', 'execute' )
at
java.security.AccessControlContext.checkPermission(AccessControlContext.java:207
)
at java.security.AccessController.checkPermission(AccessController.java:403)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
at
oracle.aurora.rdbms.SecurityManagerImpl.checkPermission(SecurityManagerImpl.java
:267)
at java.lang.SecurityManager.checkExec(SecurityManager.java:788)
at java.lang.Runtime.exec(Runtime.java:270)
at java.lang.Runtime.exec(Runtime.java:195)
at java.lang.Runtime.exec(Runtime.java:152)
at Util.RunThis(Util:10)
-1
Ending.
PL/SQL procedure successfully completed.
February 19, 2004 - 12:31 pm UTC
sorry -- i cannot reproduce on 9ir2 myself (did you log out and back in after granting?)
ops$tkyte@ORA920PC> grant dba to rt_test identified by rt_test;
Grant succeeded.
ops$tkyte@ORA920PC>
ops$tkyte@ORA920PC> begin
2 dbms_java.grant_permission
3 ('RT_TEST',
4 'java.io.FilePermission',
5 '/usr/bin/perl',
6 'execute');
7
8 dbms_java.grant_permission
9 ('RT_TEST',
10 'java.lang.RuntimePermission',
11 '*',
12 'writeFileDescriptor' );
13 end;
14 /
PL/SQL procedure successfully completed.
ops$tkyte@ORA920PC>
ops$tkyte@ORA920PC>
ops$tkyte@ORA920PC> @connect rt_test/rt_test
ops$tkyte@ORA920PC> set termout off
rt_test@ORA920PC> REM GET afiedt.buf NOLIST
rt_test@ORA920PC> set termout on
rt_test@ORA920PC>
rt_test@ORA920PC> create or replace and compile
2 java source named "Util"
3 as
4 import java.io.*;
5 import java.lang.*;
6
7 public class Util extends Object
8 {
9 public static int RunThis(String args)
10 {
11 Runtime rt = Runtime.getRuntime();
12 int rc = -1;
13
14 try
15 {
16 Process p = rt.exec(args);
17
18 int bufSize = 4096;
19 BufferedInputStream bis =
20 new BufferedInputStream(p.getInputStream(), bufSize);
21 int len;
22 byte buffer[] = new byte[bufSize];
23
24 // Echo back what the program spit out
25 while ((len = bis.read(buffer, 0, bufSize)) != -1)
26 System.out.write(buffer, 0, len);
27
28 rc = p.waitFor();
29 }
30 catch (Exception e)
31 {
32 e.printStackTrace();
33 rc = -1;
34 }
35 finally
36 {
37 return rc;
38 }
39 }
40 }
41 /
Java created.
rt_test@ORA920PC>
rt_test@ORA920PC>
rt_test@ORA920PC> create or replace
2 function RUN_CMD(p_cmd in varchar2) return number
3 as
4 language java
5 name 'Util.RunThis(java.lang.String) return integer';
6 /
Function created.
rt_test@ORA920PC>
rt_test@ORA920PC>
rt_test@ORA920PC> create or replace procedure RC(p_cmd in varchar2)
2 as
3 x number;
4 begin
5 x := run_cmd(p_cmd);
6 end;
7 /
Procedure created.
rt_test@ORA920PC>
rt_test@ORA920PC>
rt_test@ORA920PC> variable x number;
rt_test@ORA920PC> set serveroutput on
rt_test@ORA920PC> exec dbms_java.set_output(100000);
PL/SQL procedure successfully completed.
rt_test@ORA920PC>
rt_test@ORA920PC>
rt_test@ORA920PC> exec :x := RUN_CMD('/usr/bin/perl /home/tkyte/test.pl' );
Hello World
PL/SQL procedure successfully completed.
Ben, February 19, 2004 - 1:39 pm UTC
Yes - actually, the grant was in one terminal window as the SYS user, and the script execution was in another terminal, as a regular user. I just tried to disconnect/reconnect, and it still fails, but now I've lost the error messages:
@tahiti/export/home/hebben01>sqlplus
SQL*Plus: Release 9.0.1.4.0 - Production on Thu Feb 19 13:25:34 2004
(c) Copyright 2001 Oracle Corporation. All rights reserved.
Enter user-name: rocq
Enter password:
Connected to:
Oracle9i Enterprise Edition Release 9.0.1.4.0 - Production
JServer Release 9.0.1.4.0 - Production
SQL> set serveroutput on size 1000000
exec dbms_java.set_output(1000000)
SQL>
PL/SQL procedure successfully completed.
SQL> exec test_runcmd
Beginning.
-1
Ending.
PL/SQL procedure successfully completed.
February 19, 2004 - 2:37 pm UTC
put some System.out.println( "hello world" ) messages in your java.
I think you have gotten around your "permission issue" (else we'd see that) and it is now failing 'for some other reason'
Ben, February 19, 2004 - 2:53 pm UTC
This is what I tried:
create or replace and compile java source named "Util" as
import java.io.*;
import java.lang.*;
public class Util extends Object {
public static int RunThis(String args) {
Runtime rt = Runtime.getRuntime();
int rc = -1;
try {
System.out.println("Hello world 1");
Process p = rt.exec(args);
int bufSize = 4096;
BufferedInputStream bis =
new BufferedInputStream(p.getInputStream(), bufSize);
int len;
byte buffer[] = new byte[bufSize];
System.out.println("Hello world 2");
// Echo back what the program spit out
while ((len = bis.read(buffer, 0, bufSize)) != -1)
System.out.write(buffer, 0, len);
System.out.println("Hello world 3");
rc = p.waitFor();
}
catch (Exception e) {
System.out.println("Hello world 4");
e.printStackTrace();
rc = -1;
}
finally {
return rc;
}
}
}
/
Re-granted privileges as the sys user:
SQL> begin
dbms_java.grant_permission
('ROCQ',
'SYS:java.io.FilePermission',
'/usr/bin/perl',
'execute');
dbms_java.grant_permission
('ROCQ',
'SYS:java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
end;
/
PL/SQL procedure successfully completed.
Checked permissions at the OS level to make sure Oracle had the required privileges to execute the script.
But I'm still getting the same result:
SQL> exec test_runcmd
Beginning.
-1
Ending.
I'm not seeing the "hello world" messages.
February 19, 2004 - 3:01 pm UTC
are you sure you made the call to dbms_java to enable output (else it gets written to a trace file on the database server).
Until you get "output", nothing is working -- get it to get output on your screen first. Just write a hello world java snippet if you have to.
Ben, February 19, 2004 - 3:01 pm UTC
Disregard my last posting. I had neglected to logout/login again.
The new Java:
create or replace and compile java source named "Util" as
import java.io.*;
import java.lang.*;
public class Util extends Object {
public static int RunThis(String args) {
Runtime rt = Runtime.getRuntime();
int rc = -1;
try {
System.out.println("Hello world 1");
Process p = rt.exec(args);
System.out.println("Hello world A");
int bufSize = 4096;
BufferedInputStream bis =
new BufferedInputStream(p.getInputStream(), bufSize);
int len;
byte buffer[] = new byte[bufSize];
System.out.println("Hello world 2");
// Echo back what the program spit out
while ((len = bis.read(buffer, 0, bufSize)) != -1)
System.out.write(buffer, 0, len);
System.out.println("Hello world 3");
rc = p.waitFor();
}
catch (Exception e) {
System.out.println("Hello world 4");
e.printStackTrace();
rc = -1;
}
finally {
return rc;
}
}
}
/
Here is what I'm seeing:
SQL> exec test_runcmd
Beginning.
Hello world 1
-1
Ending.
PL/SQL procedure successfully completed.
February 19, 2004 - 3:04 pm UTC
put something in the finally block -- it is not making sense yet. If the rt.exec was failing -- it would jump to the catch block -- but apparently - it is not.
Ben, February 19, 2004 - 3:11 pm UTC
finally {
System.out.println("Goodbye cruel world");
return rc;
}
SQL> exec test_runcmd
Beginning.
Hello world 1
Goodbye cruel world
-1
Ending.
February 19, 2004 - 3:23 pm UTC
don't know -- sorry, i'll have to refer you to support. we know the rt.exec was working at some point (you got the permissions thing) but now is not.
Maybe try "ls" like I did to remove perl and scripting from the equation first tho
Ben, February 19, 2004 - 3:26 pm UTC
ok
Thanks for all your help, Tom.
how to send message?
Sikandar Hayat, March 09, 2004 - 6:34 am UTC
Hi,
I want to send message to different users when any insert in the table. I am using Oracle 9i r2 on Windows 2003 env. Please guide me as I am trying to use
net send sikandar A record inserted....
But unable to use net send command in the trigger.
March 09, 2004 - 12:16 pm UTC
did you install the above code that lets you run host commands?
3x for help!!!
dibo, March 21, 2004 - 10:53 pm UTC
so good.
haho.
Can PL/SQL submit a nohup job in unix shell
Stephen, April 02, 2004 - 1:43 am UTC
I try to submit a nohup shell script from pl/sql, but the session still wait unit the script end. How can I submit a nohup jobs in pl/sql?
Please advise!
April 02, 2004 - 10:06 am UTC
the script you run would call the script you want to run in the background
instead of you running:
rc( 'some_script' );
you would run
rc( 'some_other_script' );
and some_other_script would be
#!/bin/sh
some_script &
Can PL/SQL submit a nohup job in unix shell
Stephen, April 02, 2004 - 8:29 pm UTC
Hi,
I had tried the following method already in the some_other_script:
1)
#!/bin/sh
some_script &
2)
#!/bin/sh
nohup some_script &
But the session in PL/SQL still wait until the last nohup job completed.
Should you have any idea? Please advise.
Thanks,
Stephen
April 03, 2004 - 8:53 am UTC
maybe its the waitFor() call in the Process class.
in fact, google'ing waitfor process confirms.
your choices
o learn more java to find the exact solution you want
o remove the p.waitfor call so as to not block and hope that is the solution you want.
why I hate windoz #101
robert, April 13, 2004 - 2:39 pm UTC
tom,
The code below worked fine under *nix (9i) where instead of
"c:/winnt/system32/cmd", I had "/bin/sh".
But under 8i/W2K, it's not carrying out my commands:
Can you spot whats wrong, thanks
CREATE OR REPLACE AND COMPILE
JAVA SOURCE NAMED "Util"
AS
import java.io.*;
import java.lang.*;
public class Util extends Object
{
public static int RunThis(String args)
{
Runtime rt = Runtime.getRuntime();
int rc = -1;
try
{
String[] cmd = {"c:/winnt/system32/cmd", "/c", args};
Process p = Runtime.getRuntime().exec(cmd);
rc = p.waitFor();
}
catch (Exception e)
{
e.printStackTrace();
rc = -1;
}
finally
{
return rc;
}
}
}
/
CREATE OR REPLACE
FUNCTION run_host_cmd(p_cmd IN VARCHAR2) RETURN NUMBER
AS
LANGUAGE JAVA
NAME 'Util.RunThis(java.lang.String) return integer';
/
CREATE OR REPLACE PROCEDURE RC(p_cmd IN VARCHAR2)
AS
x NUMBER;
BEGIN
x := run_host_cmd(p_cmd);
END;
/
SQL> exec rc('del C:\temp\foo.pdf');
PL/SQL procedure successfully completed
---- BUT C:\temp\foo.pdf' is NOT deleted
GRANTED:
dbms_java.grant_permission('MANDA','java.io.FilePermission','c:\winnt\system32\cmd.exe','execute');
dbms_java.grant_permission('MANDA', 'java.io.FilePermission','C:/temp/*', 'read,write');
dbms_java.grant_permission('MANDA', 'java.lang.RuntimePermission','C:/temp/*', 'writeFileDescriptor' );
April 13, 2004 - 6:36 pm UTC
look in the server for a trace file -- the prints from exceptions are going there.
Disregard Prev Post - bug found
robert, April 13, 2004 - 5:26 pm UTC
tom pls disregard my prev posting.
found out what was wrong...shoulda have a space
before the parameter...duh
Thanks
SQL> exec rc(' del C:\temp\foo.pdf');
Does Oracle waits ?
Robert, April 14, 2004 - 9:28 am UTC
Tom, does Oracle, in PL/SQL processing, wait for the host call via Java SP to end then continue ?
Thanks
April 14, 2004 - 10:49 am UTC
as coded, yes --
26 while ((len = bis.read(buffer, 0, bufSize)) != -1)
27 System.out.write(buffer, 0, len);
28
29 rc = p.waitFor();
30 }
Just what we needed
Jack Boyle, April 28, 2004 - 7:46 am UTC
We have implemented a solution for executing processes outside of the database that includes Oracle Queues, detached processes, etc. This solution looks like a much cleaner, more straightforward approach.
Need to run sqlldr command from within the procedure
Anurag Mehrotra, April 29, 2004 - 7:15 pm UTC
I have already implemented the solution mentioned here to run OS commands successfully. However in spite of my best efforts I have been unable to invoke sql loader command using this method.
my exec command is:
exec :x := RUN_CMD('/export/home/oracle/test-sqlldr/load-data-test.sh mytestctl.ctl mydatafile.dat')
load-data-test.sh looks something like:
USAGE="load-data-test.sh ctlfilename.ctl datafilename.dat"
if [ $# -lt 2 ] ; then
echo "$USAGE"
exit 1 fi
ORACLE_SID=dbtest ORACLE_HOME=/usr/app/oracle/product/8.1.7 export ORACLE_SID
export ORACLE_HOME
$ORACLE_HOME/bin/sqlldr username/pwd $1 data=$2
I have also assigned the following privilege to the user:
dbms_java.grant_permission
('USERNAME',
'java.io.FilePermission',
'/usr/bin/ls',
'execute');
dbms_java.grant_permission
('USERNAME',
'java.io.FilePermission',
'/export/home/oracle/test-sqlldr/load-data-test.sh',
'execute');
dbms_java.grant_permission
('USERNAME',
'SYS:java.io.FilePermission',
'/export/home/oracle/test-sqlldr/*',
'read,write,execute');
dbms_java.grant_permission
('USERNAME',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
end;
/
Somehow it does not seem to create the log file or the bad file in the directory I am expecting it to create (/export/home/oracle/test-sqlldr). The response I get after executing the RUN_CMD is: "PL/SQL procedure successfully completed."
Could there be some permission that I am missing on the directory?
April 30, 2004 - 7:00 am UTC
well, I see no explicit "cd" anywhere -- do you have any idea what directory might be the "current working one"?
I would add a bit of "debug" to the script. redirect its output to /tmp/something, put cd's in there to be exactly where you think you should be and so on.
and don't forget, it'll run "as oracle", not as "you" so yes, permissions play into this big time.
It worked
Anurag Mehrotra, April 30, 2004 - 9:59 am UTC
'cd' did the trick.
You can write all the complex code in the world, but can forget simplest of all things, that can cause undesirable results.
Your help is greatly appreciated.
to call a Pro*C executables
Pushparaj A, May 19, 2004 - 10:50 am UTC
Tom,
Can I use this Java approach to call a Pro*C executables
from the stored procedures. Since Pro*C needs to connect back to the database, I am not sure if this is the best way.
Currently we don't have JVM installed in our database and if calling a Pro*C executable from stored procedure is feasible by this way then I can ask the manager to have the
JVM installed in the database.
We currently using,
Oracle9i Enterprise Edition Release 9.2.0.5.0 - 64bit Production
With the Partitioning option
JServer Release 9.2.0.5.0 - Production
Thanks
Pushparaj
May 19, 2004 - 11:10 am UTC
you can use this approach to call "any executable"
but if I had pro*c code I needed to invoke -- i would be looking at EXTERNAL PROCEDURES and just call the c code as a subroutine instead, it'll use the same connection, it'll use the same transaction.
Background execution
andrew, May 25, 2004 - 7:55 pm UTC
In relpy to Stephen's posting above, I've successfully used this for background execution:
#!/usr/bin/ksh
# Script: at_now.ksh
/usr/bin/echo "$1 $2 $3 $4 $5 $6 $7 $8 $9" | /usr/bin/at now
begin
RC('/full_path/at_now.ksh /usr/bin/sleep 10');
end;
/
Java procedure for host calls
RameshG, May 26, 2004 - 10:36 am UTC
I'm getting the following error when i run it:
SQL> exec rc('/usr/bin/ps -ef');
java.lang.ArrayIndexOutOfBoundsException
at Util.RunThis(Util.java:11)
DBA's have granted the permissions that you have specified.
Could explain me if anything else needs to be done.
Thanks
RameshG
May 26, 2004 - 12:47 pm UTC
ctl-f and enter ArrayIndexOutOfBoundsException into the text field...
Java procedure for host calls on Unix environment
Jose Luis Sanchez, May 27, 2004 - 1:19 pm UTC
hi tom.
I don´t know anything about java or unix and i would like to know if i could use this procedures whit sqlldr on windows xp and Oracle 9i. I´m not DBA an i would like to know if is obligatory anyone grant me permission with dbms_java.grant_permission.
thank you very much for your help
May 27, 2004 - 8:32 pm UTC
works on windows.
you need the grant permission on any OS
Works but Sqlloader is hanging and bringing the Databse down
Rajesh Chundi, June 08, 2004 - 2:36 pm UTC
Hi Tom ,
I am using the procedure RC to call sqlloader in a loop in anothe rstored proc for each input file.
if the input file is small it works
even for multiple files, but its hanging and bringing the database down whne the number of records is increased to 6000 of 1column or type number.
what am I missing please help
here is the stroed proc iam Using .
CREATE OR REPLACE PROCEDURE "TKMSYS"."LG2" AS
l_file UTL_FILE.file_type;
l_location VARCHAR2(100) := 'GRADESDIR';
l_filename VARCHAR2(100) := 'fileList.txt';
l_exists BOOLEAN;
l_file_length NUMBER;
l_blocksize NUMBER;
l_text VARCHAR2(32767);
cmdStr varchar2(4000);
procId varchar2(100);
fileSeq number(10);
retVal number(10);
BEGIN
-- Open file.
l_file := UTL_FILE.fopen(l_location, l_filename, 'r', 32767);
select 'LG' ||to_char(sysdate,'mmddyyyyhhmiss') into procId from dual;
-- Read and output first line.
UTL_FILE.get_line(l_file, l_text, 32767);
DBMS_OUTPUT.put_line('First Line: |' || l_text || '|');
-- Read through the file until we reach the last line.
BEGIN
fileSeq:= 1 ;
retVal := RUN_CMD('mkdir c:\UPHS\'||procId);
LOOP
retVal := -99;
UTL_FILE.get_line(l_file, l_text, 32767);
cmdStr := ' sqlldr TKMSYS/do1od3le5@rchundi data=c:\UPHS\' ||l_text ||
' control=c:\UPHS\test.ctl log=c:\UPHS\'||procId ||'\'||replace(l_text,'.txt','.log')||
' bad=c:\UPHS\'||procId ||'\'||replace(l_text,'.txt','.bad') ||
' discard=c:\UPHS\'||procId ||'\'||replace(l_text,'.txt','.dis') ;
-- if(fileSeq =1) then
-- RC('echo ' || cmdStr || '> c:\UPHS\'||procId ||'\loadRaw.bat');
-- else
-- RC('echo ' || cmdStr || ' >> c:\UPHS\'||procId ||'\loadRaw.bat');
-- end if;
DBMS_OUTPUT.put_line( cmdStr );
retVal:= RUN_CMD(cmdStr);
--Rc('exit');
-- DBMS_OUTPUT.put_line( l_text );
fileSeq := fileSeq + 1;
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
null;
END;
-- Rc('echo CHR(10)');
-- Output the last line.
DBMS_OUTPUT.put_line('Last Line : |' || l_text || '|');
DBMS_OUTPUT.put_line( 'c:\UPHS\'||procId ||'\loadRaw.bat' );
--RC('c:\UPHS\'||procId ||'\loadRaw.bat CHR(10)');
-- Close the file.
UTL_FILE.fclose(l_file);
END;
/
June 08, 2004 - 3:41 pm UTC
sqlldr will not "hang" or "bring down" your database.
run sqlldr from the command line (remove pieces). what happens then?
spurious OutOfMemoryException
A reader, June 16, 2004 - 3:30 pm UTC
Hi Tom,
I'm running the code practically identical to yours, and it gets called several times in succession. And sometimes I'm getting OutOfMemoryException, which gets thrown from
Process p = Runtime.getRuntime().exec(cmd);
Once I catch the first OutOfMemoryException, all the next attempts also fail, until I logout/re-login again.
Do you have any idea what could be causing it?
The command itself is a shell script that calls chmod.
The oracle version is 9.2 and it's running under AIX.
Any ideas would be much appreciated.
thanks,
ilya
June 16, 2004 - 4:02 pm UTC
"practically identical"
care to share? does it always reproduce? (eg: if you go into a hard loop and just call it over and over and ask it to run "uptime" or something innocent -- does it eventually bomb?)
spurious OutOfMemoryException
Ilya, June 16, 2004 - 4:51 pm UTC
OK, here's the java code:
public static void executeCommand(String cmd)
throws IOException, java.sql.SQLException {
Process p = Runtime.getRuntime().exec(cmd);
int res;
int bufSize = 4096;
int len;
byte[] buffer = new byte[bufSize];
try {
BufferedInputStream bis =
new BufferedInputStream(p.getInputStream(), bufSize);
//Echo back what the program spit out
while ((len = bis.read(buffer, 0, bufSize)) != -1) {
System.out.write(buffer, 0, len);
}
res = p.waitFor();
p = null;
bis.close();
bis = null;
} catch (InterruptedException ex) {
throw new RuntimeException(
"exception while waiting for the process to complete: "
+ ex.getMessage());
}
}
and here's pl/sql test code:
begin
dbms_java.set_output(1000000);
dbms_output.enable(1000000);
for i in 1 .. 100
loop
fileutils_pkg.executecommand('/homedev/ilyam/giftsedd/chmod_edd.sh');
end loop;
end;
and there's also a package fileutils_pkg with
PROCEDURE executecommand(
cmd IN VARCHAR2
)
AS
LANGUAGE JAVA
NAME 'gifts.edd.FileUtils.executeCommand(java.lang.String)';
This runs fine the first time (calling the program 100 times in succession), but usually bombs the second time with this error:
ORA-04030: out of process memory when trying to allocate 4032 bytes (ioc_make_sub2,ioc_allocate_pal)
and the printstack is
java.lang.OutOfMemoryError
at java.lang.Thread.start(Thread.java)
at oracle.aurora.java.lang.OracleProcess.newOutputStream(OracleProcess.java)
at oracle.aurora.java.lang.OracleProcess.construct(OracleProcess.java)
at java.lang.Runtime.execInternal(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at gifts.edd.FileUtils.executeCommand(FileUtils.java:241)
where line 241 is
Process p = Runtime.getRuntime().exec(cmd);
I also tried commenting out all the BufferedInputStream stuff, so that it's simply
public static void executeCommand(String cmd)
throws IOException, java.sql.SQLException {
Process p = Runtime.getRuntime().exec(cmd);
int res;
//int bufSize = 4096;
//int len;
//byte[] buffer = new byte[bufSize];
try {
/*
BufferedInputStream bis =
new BufferedInputStream(p.getInputStream(), bufSize);
//Echo back what the program spit out
while ((len = bis.read(buffer, 0, bufSize)) != -1) {
System.out.write(buffer, 0, len);
}
*/
res = p.waitFor();
p = null;
//bis.close();
//bis = null;
} catch (InterruptedException ex) {
throw new RuntimeException(
"exception while waiting for the process to complete: "
+ ex.getMessage());
}
}
but the result is exactly the same: succeeds on the first run, fails with OutOfMemoryException the second time.
thanks,
ilya
June 16, 2004 - 4:58 pm UTC
how is your java pool size?
spurious OutOfMemoryException
Ilya, June 16, 2004 - 5:12 pm UTC
sorry, I don't know much about java pool size. What do I need to check?
June 16, 2004 - 6:09 pm UTC
spurious OutOfMemoryException
Ilya, June 16, 2004 - 8:15 pm UTC
NAME TYPE VALUE
------------------------------------ ----------- ----------
java_max_sessionspace_size integer 0
java_pool_size big integer 218103808
java_soft_sessionspace_limit integer 0
June 17, 2004 - 7:59 am UTC
I'll have to request you file a tar with support. possible memory leak.
spurious OutOfMemoryException
A reader, June 17, 2004 - 10:53 am UTC
while in the process of creating a tar, I found a similar report of memory leak problem with oracle's JVM, reproducible in 9.2.0.2; it was fixed in 10.0.0
ArrayIndexOutOfBounds
Chris Fischer, June 17, 2004 - 5:18 pm UTC
I've read all the suggestions of going back and doing a ctrl-f to find the comment about this exception.
Here's my problem though. The documented construct for passing an array of strings to a java method in a pl/sql wrapper is to have it declared like this:
public class EchoInput {
public static void main (String[] args) {
for (int i = 0; i < args.length; i++)
System.out.println(args[i]);
}
}
To publish method main, you might write the following call spec:
CREATE OR REPLACE PROCEDURE echo_input (
s1 VARCHAR2,
s2 VARCHAR2,
s3 VARCHAR2)
AS LANGUAGE JAVA
NAME 'EchoInput.main(java.lang.String[])';
This is taken directly from the 9iR2 Java Stored Procedure Developers Guide.
In addition, I have an 8i app that I'm trying to upgrade to 9i, and all my calls to methods similarly fail with ArrayIndexOutOfBounds. I can't believe that Oracle would make a change to the callspec in such a way as to BREAK everyone's app? Oh, I guess everyone being the 5 foolish people to actually USE java in the database.
June 17, 2004 - 6:42 pm UTC
in my case, i had a bug in the code (i did it wrong). I was not passing an array of strings.
I'm not sure what you are trying to say?
can you give me a complete test case in the fashion I give to you? with the create or replace java, etc etc etc.
Memory leak
John Dunn, July 14, 2004 - 9:00 am UTC
I am using the following code to run unix commands. I have minimised the memory issues by including a call to the garbage collector, but occasionally it is returning a rc of 3. However I do not know how to output details of the exception. I would like to output the error details to a file. Can anyone help with that?
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "function_os_command" AS
import java.io.*;
import java.util.*;
public class function_os_command
{
public static int Run(String Command)
{
int rc = 0;
try
{
Runtime rt = Runtime.getRuntime();
Process p = rt.exec(Command);
try {
rc = p.waitFor();
} catch (InterruptedException intexc) { rc = 2; }
rt.gc();
} catch (Throwable t) { rc = 3; }
return(rc);
}
}
/
This Example is Not working On Oracle 9i R2 on Windows
Harshad Savot, July 14, 2004 - 11:04 am UTC
I have tried this example on Oracle 9i R2 Windows.
java.lang.ArrayIndexOutOfBoundsException
at Util.RunThis(Util:14).
What Should change in code so It can works on Windows Platform. Please give any example .
Thanks
Harshad
July 14, 2004 - 12:04 pm UTC
ctl-f for arrayindexoutofbounds on this page......... search for that word -- asked and answered.
Having an issue calling a sqlplus shell...
Kelly Taylor, July 23, 2004 - 9:02 pm UTC
Tom,
I'm having a problem using run_cmd in my package for starting dynamic SQL*Plus sessions; I want to pass a connection string and PL/SQL block to a shell script for execution. Everything works fine when calling exp or others, which I've included below. I think it's a quoting problem but I can't seem to find a solution other than completely reformatting the SQL and using sed. If you would provide any insight or advice, I'd seriously appreciate it. :) RDBMS/OS --> 9.2.0.4/Solaris 8
My code:
--
-- TEST TABLE
--
create table exp_test(id number(22));
--
-- THIS PROC WORKS SHOWING JAVA AND PERMS ARE CORRECT,
-- I USED YOUR LATEST CODE.
--
create or replace procedure run_exp(
p_exp_conn in varchar2, -- USERID=
p_table_name in varchar2, -- TABLES=
p_dmp_file in varchar2, -- FILE=
p_log_file in varchar2 ) -- LOG=
is
--
-- Example call:
-- exec run_exp('user/pass@sid',
-- 'exp_test',
-- '/tmp/exp_test.dmp',
-- '/tmp/exp_test.log');
--
l_exp_cmd varchar2(2000) := '/tmp/run_exp.sh';
l_return number := 0;
begin
l_exp_cmd := l_exp_cmd ||' "'|| p_exp_conn
||'" "'|| p_table_name
||'" "'|| p_dmp_file
||'" "'|| p_log_file
||'"';
l_return := run_cmd(l_exp_cmd);
if l_return = 0 then
dbms_output.put_line('Exp session succeeded.');
else
dbms_output.put_line('Exp session failed.');
end if;
exception
when others then
raise;
end run_exp;
/
--
-- THIS IS THE PROBLEM PROC OR QUOTING PROBLEM
--
create or replace procedure run_sqlplus(
p_sqlplus_conn in varchar2,
p_sqlplus_qry in varchar2,
p_spool_file in varchar2 )
is
--
-- Sample call:
-- exec run_sqlplus('user/pass@sid',
-- 'begin dbms_output.put_line(''Hello''); end;',
-- '/tmp/run_sqlplus.log');
--
l_sqlplus_cmd varchar2(2000) := '/tmp/run_sqlplus.sh';
l_return number := 0;
begin
l_sqlplus_cmd := l_sqlplus_cmd ||' '|| p_sqlplus_conn
||' "'|| p_sqlplus_qry
||'" "'|| p_spool_file
||'"';
dbms_output.put_line(l_sqlplus_cmd);
l_return := run_cmd(l_sqlplus_cmd);
if l_return = 0 then
dbms_output.put_line('SQL*Plus session succeeded.');
else
dbms_output.put_line('SQL*Plus session failed.');
end if;
exception
when others then
raise;
end run_sqlplus;
/
--
-- SAMPLE SHELL SCRIPTS
--
#!/bin/sh
#
# run_exp.sh
# -------------------------
#
echo userid = $1
echo tables = $2
echo file = $3
echo log = $4
exp userid=$1 tables=$2 file=$3 log=$4 statistics="none" direct="yes"
#!/bin/sh
#
# run_sqlplus.sh
# -------------------------
#
echo conn = $1
echo query = $2
echo spoolfile = $3
sqlplus -s /NOLOG << EOF
connect $1
set serverout on
spool $3
set timing on
begin
$2
end;
/
spool off
exit
EOF
--
-- TEST sh SCRIPTS
--
$ /tmp/run_exp.sh "user/pass@sid" "exp_test" "/tmp/exp_test.dmp" "/tmp/exp_test.log"
result:
-------
. . exporting table EXP_TEST 0 rows exported
Export terminated successfully without warnings.
$ /tmp/run_sqlplus.sh "user/pass@sid" "begin dbms_output.put_line('Hello'); end;" "/tmp/run_sqlplus.log"
result:
-------
conn = user/pass@sid
query = begin dbms_output.put_line('Hello'); end;
spoolfile = /tmp/run_sqlplus.log
Connected.
Hello
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.16
--
-- TEST PROCS
--
set serveroutput on size 1000000
exec dbms_java.set_output(1000000);
SQL> exec run_exp('user/pass@sid', 'exp_test', '/tmp/exp_test.dmp', '/tmp/exp_test.log');
PL/SQL procedure successfully completed. (new dmp file and log were created)
SQL> exec run_sqlplus('user/pass@sid','begin dbms_output.put_line(''Hello''); end;','/tmp/run_sqlplus.log');
/tmp/run_sqlplus.sh user/pass@sid "begin dbms_output.put_line('Hello'); end;" "/tmp/run_sqlplus.log"
conn = user/pass@sid
query = "begin
spoolfile = dbms_output.put_line('Hello');
Connected.
ERROR:
ORA-01740: missing double quote in identifier
Elapsed: 00:00:00.00
SQL*Plus session succeeded.
PL/SQL procedure successfully completed.
July 24, 2004 - 11:13 am UTC
whitespace will kill you everytime when you have sh's calling shells and so on.
easiest to just "avoid the issue"
user/pass@connect should never have whitespace
we'll make the reasonable assumption that your spool file name won't either
but the query will....
so arg1 and arg2 are "one word"
arg3 is the rest.
we change the script to be:
#!/bin/sh
#
# run_sqlplus.sh
conn=$1
shift
spoolfile=$1
shift
query=$*
echo conn = $conn
echo query = $query
echo spool = $spoolfile
sqlplus -s /NOLOG << EOF
connect $conn
set serverout on
spool $spoolfile
set timing on
begin
$query
end;
/
spool off
exit
EOF
and the plsql to be:
ops$tkyte@ORA9IR2> create or replace procedure run_sqlplus(
2 p_sqlplus_conn in varchar2,
3 p_sqlplus_qry in varchar2,
4 p_spool_file in varchar2 )
5 is
6 --
7 -- Sample call:
8 -- exec run_sqlplus('user/pass@sid',
9 -- 'begin dbms_output.put_line(''Hello''); end;',
10 -- '/tmp/run_sqlplus.log');
11 --
12 l_sqlplus_cmd varchar2(2000) := '/tmp/run_sqlplus.sh';
13 l_return number := 0;
14
15 begin<b>
16 l_sqlplus_cmd := l_sqlplus_cmd ||' '|| p_sqlplus_conn
17 ||' '|| p_spool_file
18 ||' '|| p_sqlplus_qry;
19</b>
20 dbms_output.put_line(l_sqlplus_cmd);
21
22 l_return := run_cmd(l_sqlplus_cmd);
23
24 if l_return = 0 then
25 dbms_output.put_line('SQL*Plus session succeeded.');
26 else
27 dbms_output.put_line('SQL*Plus session failed.');
28 end if;
29
30 exception
31 when others then
32 raise;
33 end run_sqlplus;
34 /
Procedure created.
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> set serveroutput on
ops$tkyte@ORA9IR2> exec dbms_java.set_output(100000);
PL/SQL procedure successfully completed.
ops$tkyte@ORA9IR2> exec run_sqlplus('/', 'begin dbms_output.put_line(''Hello''); end;', '/tmp/run_sqlplus.log' );
/tmp/run_sqlplus.sh / /tmp/run_sqlplus.log begin dbms_output.put_line('Hello');
end;
conn = /
query = begin dbms_output.put_line('Hello'); end;
spool = /tmp/run_sqlplus.log
Connected.
Hello
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.00
SQL*Plus session succeeded.
PL/SQL procedure successfully completed.
More permissions problems
Mike, July 26, 2004 - 11:58 am UTC
Tom, this is great stuff. As usual. However, I've read all the various permissions solutions in the article so far, but am still having problems.
Calling ls, ps, etc all works great. However, I cannot get any user scripts to run. I created a test script in the Oracle users home directory, owned by Oracle (who also owns and started the database) and checked the execute permissions. Script runs fine at the command line as Oracle, but I get nothing in SQL*Plus and nothing in my debug.txt file when I run it via pl/sql. I granted permissions on /usr/bin/whoami just to verify that Oracle is the user executing these scripts and it is.
Here's my test script:
ls
echo "This is a test..."
date > debug.txt
Any additional thoughts? I'm stumped.
July 26, 2004 - 1:24 pm UTC
put a #!/bin/sh at the top, and echo $PATH and other things, check out the environment.
Thanks!
Mike, July 26, 2004 - 1:36 pm UTC
#!/bin/sh solves the problem. Obviously didn't even think of that one. Sorry to bug you with something so simple.
run remotely
fz, October 18, 2004 - 3:30 am UTC
It runs fine locally, but the result does not show up when running remotely through a db_link. did I miss sth?
LOCAL:
SQL> exec rc('/bin/sar -u 3 3');
....
23:54:34 %usr %sys %wio %idle
23:54:37 0 2 2 96
23:54:40 0 0 2 98
23:54:43 0 0 1 99
Average 0 1 1 98
PL/SQL procedure successfully completed.
REMOTE:
SQL> set serveroutput on size 1000000
SQL> exec dbms_java.set_output(1000000)
PL/SQL procedure successfully completed.
SQL> exec rc@xxx('/bin/sar -u 3 3');
PL/SQL procedure successfully completed.
SQL>
October 18, 2004 - 8:20 am UTC
when you run the remote procedure -- its "dbms_output" stuff (java output stuff) goes to the REMOTE dbms_output package too.
sqlplus runs dbms_output.get_lines() after each statement to see if there is anything to print -- there isn't anything "local". It doesn't know to look at dbms_output@xxx to get the output.
You'd have to do that yourself -- call dbms_output@xxx to get the lines and use the "local" dbms_output to print them.
Is calling Unix shell from Java sp a reliable way in prod?
Mark Gokman, October 18, 2004 - 2:49 pm UTC
In reference to the original question and examples in this thread. Is this a safe and reliable way of communicating with the OS? I'm not that familiar with JVM in general and the way Oracle runs it, but if JVM is a part of Oracle kernel, then allowing the application to talk almost directly to the OS seems to be strange. For example, what if i call a shell script that changes the structure of the database, or something else that can affects the entire instance? Is there any protection against such operations?
October 19, 2004 - 7:40 am UTC
what if you call a stored procedure that alters the structure of the database??
what if you call a stored procedure that affects the entire instance??
not sure what you are concerned about -- YOU write the script, YOU own the script. the script does what you told it to do. This is no less safe than running a pro*c application as Oracle on the database server (well, wait, it is probably lots more safe)
Why is it more secure?
mark Gokman, October 19, 2004 - 1:32 pm UTC
Could you please explain why running os calls from Java sp is more secure and safe than running pro*c on the server as Oracle?
October 19, 2004 - 1:52 pm UTC
Pro*c running on the server as Oracle can issue:
system( "rm -rf /home/oracle/" );
Java stored procedures can only run RM if the DBA has said "ok, you can run rm", you have the ability to grant execute on individual OS programs to java stored procedures.
A C program can run anything it wants.
Heck, the C program running as Oracle could attache the SGA if it felt like it (fun stuff maybe...)
you have very very granual access control over the java stored procedure, making it more securable (as long as you don't grant access to "*" or something.
How can pass the parameters ?
raman, October 20, 2004 - 5:51 pm UTC
Hello Tom,
This topic has given me an idea how I can execute host calls from PL/SQL in Oracle server. Finally, I am using like this:
SET SERVEROUTPUT ON SIZE 1000000
CALL DBMS_JAVA.SET_OUTPUT(1000000);
BEGIN
Host_Command (p_command => 'sdelayer -o delete -l TRM_RP_GEOMETRICS_MV,GEOMETRY -i esri_sde9i -s jj00WB316 -u gisteam -p gisteam -N -q');
END;
/
It does SDE registration in Oracle Spatial database.
Table name: TRM_RP_GEOMETRICS_MV
Column Name: Geometry
Username:GISTEAM
Pwd:GISTEAM
Database: JJ00WB316
It is executed successfully. I have to execute such Host_Command procedure 12 times in part of a PL/SQL script for different purposes.
Like that, I have 40 PL/SQL scripts with different table name,column name etc...
Now, I would like to create a procedure which will accept the parameters like tablename,columnname etc....pass them to HOST_COMMAND procedure to execute the DOS command. So, that I don't need to maintain in those 40 scripts.
So, how can I make the HOST_COMMAND procedure accept these parameters??
Example:
CREATE OR REPLACE PROCEDURE A (TABLENAME,COLUMNNAME)
AS
BEGIN
Host_Command (p_command => 'sdelayer -o delete -l <TABLENAME>,<COLUMNNAME> -i esri_sde9i -s jj00WB316 -u gisteam -p gisteam -N -q');
Host_Command (...);
Host_Command (...);
..
..
End;
It would be very helpful to me, if you could give me a solution.
regards,
-raman
October 20, 2004 - 8:56 pm UTC
... p_command => 'sdelayer -o delete -l ' || l_table_name || ',' || l_column_name || ' -i ....
just concatenate them into the string.
raman, October 25, 2004 - 11:01 am UTC
Thankyou verymuch ...
but what about this....
Roel, November 25, 2004 - 9:09 am UTC
I created a java program and wrapped it in PL/SQL. I would like to use it to unzip a certain file:
In SQLPLUS >
exec host.run('/bin/unzip -L /app/dphrmo/pvc/f0016741.113 -d /app/dphrmo/pvc/');
Archive: /app/dphrmo/pvc/f0016741.113
PL/SQL-procedure succesfully completed.
But no extraction is made. When I execute the complete command at the Unix prompt the unzip is succesful. When I try to unzip a file - in PLSQL - that already exists, the program 'hangs' logically, because it's waiting to enter a Yes/No/Cancel action for overwriting.
But why is the unzip-action not succesfull?
November 25, 2004 - 10:21 am UTC
umm, hows about the entire example. for all i know you are catching and hiding all errors in your java program.
Roel, November 26, 2004 - 3:04 am UTC
The entire (java) program is:
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "Host" AS
import java.io.*;
import java.sql.*;
import java.util.*;
public class Host
{
public static void Dir(String directory)
throws SQLException
{
File path = new File( directory );
String[] list = path.list();
String element;
for(int i = 0; i < list.length; i++)
{
element = list[i];
#sql { INSERT INTO DIR_LIST (FILENAME)
VALUES (:element) };
}
}
public static int Run(String Command)
{
Runtime rt = Runtime.getRuntime();
int rc = -1;
try
{
Process p = rt.exec(Command);
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;
}
}
}
/
So (IMHO) the errors are catched but not hided...
Before running the PL/SQL command I also ran:
>exec dbms_java.set_output(1000000)
So what can be wrong?
November 26, 2004 - 9:26 am UTC
add debug -- lots of System.out.println's and make sure you can see them.
did you set serveroutput on as well?
Solved!
Roel, November 26, 2004 - 10:47 am UTC
I moved the p.waitFor() direct after the exec(Command) and read out the ErrorStream. Apparently the user (Oracle?) was not allowed to write in the specified directory....
Now it works! Thanx a lot!
Run Java program at Unix file system using Java Stored Procedure using same example.
Mayank, December 08, 2004 - 6:26 pm UTC
I tried the same steps mention by you and grant permissions to all the files.
I am able to run a shell script which contains unix commands, but I am not able to run a small HelloWorld Java program from the shell script.
I want to run a java program from the shell script and call that shell script from the stored procedure in question.
December 09, 2004 - 12:51 pm UTC
then you need to figure out why?
your environment is most likely NOT AT ALL what you think it is. Your path is going to be Oracle's path, your environment is going to be Oracle's environment.
read the followup above that can be found by ctl-f'ing for
ran as ORACLE
on this page.
Mayank, December 08, 2004 - 6:38 pm UTC
SQL> exec rc('/usr/bin/sh /home/dhscrp/pass.sh');
run_cmd returned : 1 for /usr/bin/sh /home/dhscrp/pass.sh
PL/SQL procedure successfully completed.
------------------------------------------------
create or replace procedure RC(p_cmd in varchar2)
as
x number;
begin
x := run_cmd(p_cmd);
--execute immediate('set serveroutput on size 1000000');
--dbms_java.set_output(1000000);
DBMS_OUTPUT.PUT_LINE ( 'run_cmd returned : '||rpad(x, 3, ' ')||' for '||p_cmd);
end;
/
----------------------------------------------------
SQL> create or replace function RUN_CMD( p_cmd in varchar2) return number
2 AUTHID CURRENT_USER as language java
3 name 'OSUtil.RunThis(java.lang.String) return integer';
4 /
-------------------------------------------------------
create or replace and compile java source named "OSUtil" as
import java.io.*;
import java.lang.*;
public class OSUtil extends Object
{
public static int RunThis(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;
}
}
}
/
-------------
I used the same to call a shell script contains java commands to run one java class from Unix OS. It is not doing any thing though it is working for the shell script which contains unix commands only.
December 09, 2004 - 12:59 pm UTC
see above
Tom you are the best!!!, December 16, 2004 - 1:18 pm UTC
Tom,
Host command via java stored procedures works fine for us.But each time it generates a .trc (trace files) in user dump destination like show below.How we can stop generating this sort of trace files?
dump file c:\oracle\admin\reds\udump\reds_ora_11844.trc
Thu Dec 16 13:10:56 2004
ORACLE V9.2.0.5.0 - Production vsnsta=0
vsnsql=12 vsnxtr=3
Windows 2000 Version 5.2 , CPU type 586
Oracle9i Enterprise Edition Release 9.2.0.5.0 - Production
With the OLAP and Oracle Data Mining options
JServer Release 9.2.0.5.0 - Production
Windows 2000 Version 5.2 , CPU type 586
Instance name: reds
Redo thread mounted by this instance: 1
Oracle process number: 33
Windows thread id: 11844, image: ORACLE.EXE
*** 2004-12-16 13:10:56.590
*** SESSION ID:(35.2353) 2004-12-16 13:10:56.497
C:\oracle\ora92\DATABASE>cmd /k "c:\reds_lims_labels\print_commands\warehouse_medium.cmd C:\reds_lims_labels\13105656CHENNK.lbl > c:\reds_lims_labels\warehouse_medium.log"
December 16, 2004 - 1:36 pm UTC
you didn't open up cmd did you???
keys, kingdom come to mind -- you didn't dbms_java and give permissions on cmd?
as usual you are the best tom
you are the best tom, December 16, 2004 - 2:58 pm UTC
.cmd file is working via this java procedure.Can we turn off the trace file generations?
December 16, 2004 - 3:39 pm UTC
i'm talking about
...> cmd /k ...
are you using cmd????!? that would be "the keys to the kingdom".
A reader, December 16, 2004 - 3:56 pm UTC
Thanks! We didn't give permission on cmd /k .
We only gave execute permission on the following file.
c:\reds_lims_labels\print_commands\warehouse_medium.cmd .
December 16, 2004 - 5:08 pm UTC
why do i see cmd /k in there then?
C:\oracle\ora92\DATABASE>cmd /k
"c:\reds_lims_labels\print_commands\warehouse_medium.cmd
C:\reds_lims_labels\13105656CHENNK.lbl >
c:\reds_lims_labels\warehouse_medium.log"
?
but all you are seeing is the system.out. stuff -- meaning, you didn't call the dbms_java.setoutput to redirect stdout to the dbms_output buffer.
if you run the example "as is" from sqlplus - do you get the trace file then?
A reader, December 16, 2004 - 4:09 pm UTC
Let me explain again.Sorry I din't make it clear.
We didn't give direct permission to cmd /k .
We gave permission to execute the following file
c:\reds_lims_labels\print_commands\submit_warehouse_medium.cmd
submit_warehouse_medium.cmd has the following lines :
cmd /k "c:\reds_lims_labels\print_commands\warehouse_medium.cmd %1 > c:\reds_lims_labels\warehouse_medium.log"
Thanks Tom! Do we have anyway to turn off these trace file generations.
December 16, 2004 - 5:10 pm UTC
ok, do you have the stdout redirection going -- do you see this if you run the example as is from sqlplus with all of the commands I've got there.
A reader, December 17, 2004 - 2:11 pm UTC
SQL> execute dbms_java.set_output(99999);
PL/SQL procedure successfully completed.
SQL> set serverout on;
SQL> variable a number;
SQL> execute :a := java_mail_stuff.run_cmd('c:\reds_lims_labels\print_commands\call_ware
.cmd c:\reds_lims_labels\13032121AGARWALAR.lbl');
C:\oracle\ora92\DATABASE>cmd /k
"c:\reds_lims_labels\print_commands\warehouse_medium.cmd
c:\reds_lims_labels\13032121AGARWALAR.lbl >
c:\reds_lims_labels\warehouse_medium.log"
PL/SQL procedure successfully completed.
It didn't generate the trace file when I execute it from the sqlplus. Thanks!
December 17, 2004 - 3:14 pm UTC
you needed to redirect system.out ...
A reader, December 17, 2004 - 4:30 pm UTC
Did you mean that if we do "2>>&1 " like shown below then it would not generate the trace files?
cmd /k "c:\reds_lims_labels\print_commands\warehouse_medium.cmd %1 > c:\reds_lims_labels\warehouse_medium.log" 2>>&1
December 18, 2004 - 8:38 am UTC
no, i mean the dbms_java setoutput command redirected the system.out stuff to "dbms_output", by default, that stuff goes to the tracefile.
did you see how in sqlplus you saw on the screen what you normally see in the trace file?
Is it a good idea starting backup script using this technique
A reader, December 18, 2004 - 7:24 pm UTC
I have writen a Java SP to run a host script as mentioned above, and this scripts starts my backup script (since SP waits for the first script to end I wrote an intermadiate script). I have scheduled the SP to start my backup script using DBMS_JOB. All works fine.
Before going to distribute it to 2046 Oracle sites, I want to ask that, is this a good idea for starting backup using this technique?
December 19, 2004 - 10:35 am UTC
People typically use scripts outside of the database (eg: via rman or someother backup utility) to do this. It would be unusual to initial the backup from inside the database.
Not having reviewed you code (not saying that we want youy to post it all here!) I cannot say if this is a good idea (tm) or not. If you have tested this 100% and have a backout plan in place, sure.
A reader, December 20, 2004 - 8:09 pm UTC
Thank you for your response.
We have more than 2000 oracle remote sites. Operators of these sites even don't know (and dont care) if they have a DB. We have to perform backups on behalf of the site users.
The users' creativity on destruction made the simple backup script to a backup and one click recovery program.
Most of the sites have only one computer, so rman cannot be used. Using third party backup tools is not feasable for small sites.
Therefore we have to use the backup scripts. The problem comes out managing start time of backup (If we dont start backups, clients never take a backup). Scheduling backup using OS tools (eg. at command) needs administrator password that users dont know, even if they know it is hard to force them to schedule. But scheduling using Oracle job is as simple as running a sql script.
I know scheduling backup using oracle jobs is unusual, that is why I am asking if it is a good idea.
I don't know if here is the right place for the story. Any way here is the code that I use.
------------------------------------------------------------
the java code
------------------------------------------------------------
import java.io.*;
public class Dba {
public Dba() {
}
public static void main(String[] args) {
Dba dba = new Dba();
String arg="";
System.out.println(args[0]);
if (args.length>0) arg=args[0];
runDba(arg);
}
public static void runProcess (String program){
Process proc;
Runtime rt;
rt = Runtime.getRuntime();
try {
proc = rt.exec(program);
Thread.sleep(1000);
}
catch (Exception ex) {
ex.printStackTrace();
}
}
public static void runDba(String param){
runProcess(param);
}
}
------------------------------------------------------------
load java -user <username>/<password> Dba.class
------------------------------------------------------------
create or replace procedure jrun(param varchar2)
as language java
name 'Dba.runDba(java.lang.String)';
/
------------------------------------------------------------
startbackup.bat
------------------------------------------------------------
c:
cd c:\
start %1 %2 %3 (%2 & %3 are optional parameters)
exit
------------------------------------------------------------
backup.bat
------------------------------------------------------------
c:
cd c:\
@setlocal
set CommonProgramFiles=C:\Program Files\Common Files
set COMPUTERNAME=IBRAHIM
set HOMEDRIVE=C:
set HOMEPATH=\Documents and Settings\iozturk
set LOGONSERVER=\\IBRAHIM
set OS=Windows_NT
set Os2LibPath=C:\WINNT\system32\os2\dll;
set Path=C:\Program Files\Java\jdk1.5.0\bin;D:\oracle\product\10.1.0\db\bin;D:\oracle\product\10.1.0\db\jre\1.4.2\bin\client;D:\oracle\product\10.1.0\db\jre\1.4.2\bin;C:\jdk1.5.0\jre\bin;C:\j2sdk1.4.2_05\jre\bin;D:\JBuilderX\jdk1.4\bin;C:\WINNT\system32;C:\WINNT;C:\WINNT\System32\Wbem;C:\Program Files\Symantec\pcAnywhere\;D:\JBuilderX\jdk1.4\bin;D:\Program Files\Adabas\bin;D:\Program Files\Adabas\pgm; D:\Program Files\StarOffice7\program;
set PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH
set ProgramFiles=C:\Program Files
set SystemDrive=C:
set SystemRoot=C:\WINNT
set TEMP=C:\DOCUME~1\iozturk\LOCALS~1\Temp
set TMP=C:\DOCUME~1\iozturk\LOCALS~1\Temp
set USERDOMAIN=IBRAHIM
set USERNAME=iozturk
set USERPROFILE=C:\Documents and Settings\iozturk
C:\j2sdk1.4.2_05\bin\java -cp "%HOMEPATH%\dba_scripts\bin;%HOMEPATH%\dba_scripts\bin\lib\jbcl.jar;%HOMEPATH%\dba_scripts\bin\lib\classes12.jar;%HOMEPATH%\dba_scripts\bin\lib\jdom.jar" dbaController.DbaController backup
REM C:\j2sdk1.4.2_05\bin\java -cp C:\dba_scripts\bin;c:\dba_scripts\bin\lib\jbcl.jar;C:\dba_scripts\bin\lib\classes12.jar;c:\dba_scripts\bin\lib\jdom.jar dbaController.DbaController backup
@endlocal
exit
------------------------------------------------------------
finally schedule it to every friday at 19 PM
VARIABLE jobno NUMBER
BEGIN
DBMS_JOB.SUBMIT(:jobno,
'jrun(''c:\startbackup.bat c:\backup.bat OraLisener stop'');',
SYSDATE, 'NEXT_DAY(TRUNC(SYSDATE), ''CUMA'') + 19/24');
COMMIT;
END;
/
------------------------------------------------------------
December 20, 2004 - 8:28 pm UTC
<quote>
I know scheduling backup using oracle jobs is unusual, that is why I am asking
if it is a good idea.
</quote>
the definition of catch-22 here....
It is unusual, therefore I have no real experience with it, hence I cannot commit to saying "good thing" or "bad thing".
I'd probably rather (especially with 2000 of these things) rather have a program that is a little more "in tune with what is happening". How can you tell if this worked or not?
So, using dbms_job -- probably OK
but using a bat file? probably not ok, i'd want something more sophisticated. Maybe your actual backup program is, but I cannot see that here. I'd want a log reported into a central repository or something.
partly successful, but running into a problem
Anurag Mehrotra, February 05, 2005 - 11:32 am UTC
In the past I have successfully implemented the solution mentioned here, now I am trying to take it to the next level.
I am trying to generate Sql loader control file and shell script (on Unix platform) based on parameters passed to a sp and then call the solution mentioned here to launch the shell script.
At first I was running into the following problem:
java.security.AccessControlException: the Permission (java.io.FilePermission <<ALL FILES>> execute has not been granted.
I resolved this by granting the following permision:
dbms_java.grant_permission
('IMPORTUSER',
'SYS:java.io.FilePermission',
'<<ALL FILES>>',
'read,write,execute')
In order to execute the generated shell script, I need to assign the 'x' privilege at the os level, so I granted the following privilege:
dbms_java.grant_permission
('IMPORTUSER',
'java.io.FilePermission',
'/usr/bin/chmod',
'execute');
In spite of all this when I issue the chmod command, and try to launch the shell script, it does nothing:
cmd_return_code := osCommandRun('chmod 744 ' || v_FileDirectory || '/' || v_ShFileName );
cmd_return_code := osCommandRun(v_FileDirectory || '/' || v_ShFileName || ' ' ||
v_CtlFileName || ' ' || a_Data_File_Name );
Sqlplus simply reports "PL/SQL procedure successfully completed", but the permission is neither changed nor the shell script is executed.
Am I missing something here?
February 05, 2005 - 11:40 am UTC
why aren't you just using the much easier external table capability???
lauching shell scripts -- and not having them work -- always means "your environment isn't at all what you anticipated"
remember, it is NOT your environment
it is NOT your shell.
it is not alot of things
but --tell me, why no external tables?
followup about shell script
Anurag Mehrotra, February 05, 2005 - 11:58 am UTC
I would have loved to use external tables, but using external tables is not an options.
Damn Corporate security standards. External tables are not on the approved list.
In the meantime I added some debugging statements right as follows:
cmd_return_code := osCommandRun('chmod 744 ' || v_FileDirectory || '/' || v_ShFileName );
DBMS_OUTPUT.PUT_LINE('chMod Command= ' || to_char(cmd_return_code));
cmd_return_code := osCommandRun(v_FileDirectory || '/' || v_ShFileName || ' ' ||
v_CtlFileName || ' ' || a_Data_File_Name );
DBMS_OUTPUT.PUT_LINE('SqlLoader Launch Command= ' || to_char(cmd_return_code));
both return the code of 255.
February 06, 2005 - 3:06 am UTC
it is always an option.
would you mind pointing out to the security dudes that external tables are somewhat SAFER then permitting you to run a script as "oracle", on the OS, able to do anything "oracle" is allowed to do, including rm -rf $ORACLE_HOME
your script is not running due to differences in the environment, could be as simple as "i don't know what shell to run" - eg: a missing #!/bin/sh for exmaple.... to the environment is not really setup right.
start small, just try to get:
#!/bin/sh
env
to run or something.
problem somewhat isolated
Anurag Mehrotra, February 06, 2005 - 9:47 am UTC
I will again try to convince the security team about external tables.
I can successfully execute any shell script from within a PL/Sql procedure as mentioned here as long as it has the x (execute) privilege set for oracle.
My problem is that I have to create shell script and the control file on the fly (within the stored procedure), I need to first make it x executable to be able to run it.
In spite of granting exclusive x privilege on chmod it does not change the permission and hence cannot execute the shell script. I get a return code of 255 as opposed to 0.
cmd_return_code := osCommandRun('chmod 744 ' || v_FileDirectory || '/' || v_ShFileName );
If I change the permission to 744 for the same file manually at the os level, and re-run the stored procedure, asking for the same file name to be generated, it preserves the execute permission and the successfully executes the shell script to launch the sql loader.
This makes me believe that I am having some trouble running chmod command due to some file permissions.
Any ideas?
figured my problem
Anurag Mehrotra, February 06, 2005 - 1:37 pm UTC
I finally figured out my problem:
I had granted the following java permission:
dbms_java.grant_permission
('IMPORTUSER',
'java.io.FilePermission',
'/usr/bin/chmod',
'execute');
but the command to change the permission would not work.
cmd_return_code := osCommandRun('chmod 744 ' || v_FileDirectory || '/' || v_ShFileName );
so I changed the command to:
cmd_return_code := osCommandRun('/usr/bin/chmod 744 ' || v_FileDirectory || '/' || v_ShFileName );
All I did was to prefix chmod with /usr/bin/ and it started working. Even though 'oracle' path was setup correctly with /usr/bin:/usr/ccs/bin:/usl/local/bin: and so on.
I am thinking that when an OS command is executed from within PL/Sql Procedure, it runs in it's own shell and does not inherit any environment/path variables of the parent (in this case 'oracle' user).
Please correct me if I am wrong here.
February 07, 2005 - 3:59 am UTC
/usr/bin/chmod <> chmod
that was the cause. if you granted yourself chmod, chmod would work. you granted /usr/bin/chmod, not chmod, so only /usr/bin/chmod will work (if you are specific in one place, you must be so in others)
it makes me laugh in a sad way that your "security" team lets you create any arbitrary shell script and execute it as Oracle - but you cannot use external tables.
How sad and misguided is that. There is zero percent chance I would let anyone create a shell script on the fly like that in real life. How dangerous is that? How insecure is that? How totally POWERFUL is that ability. You can do pretty much anything you want (on purpose by by accident!!!!!)
Trying to exeute a batch file that calls windows scheduler 'AT'
Steve Montgomerie, February 07, 2005 - 10:10 am UTC
Tom,
I am using your procedure here with some success.
I have tested with a simple batch file that does time /t>> c:\temp\test.log. That works fine.
What I want to do is to schedule a job to run on another server
through windows AT. For this my batch file contents looks like 'at \\AAAAAAAA 10:34 C:\TEMP\STOP_APP_SERVER.BAT'. I can run this through the command line and also double click the batch file to schedule the job. When Oracle however executes the batch file it does not get scheduled - the procedure completes to success but no joy on the scheduling.
I execute it through Oracle like so
SQL> variable x number;
SQL> set serveroutput on
SQL> exec dbms_java.set_output(100000);
PL/SQL procedure successfully completed.
SQL> exec :x := RUN_CMD('C:\TEMP\SCHEDULE_APP_SERVER_SHUT.BAT');
D:\oracle\ora92\DATABASE>at \\orlq1aza 14:26 C:\TEMP\STOP_APP_SERVER.BAT
PL/SQL procedure successfully completed.
SQL> commit;
February 07, 2005 - 11:03 am UTC
on windows -- the oracle process is executing as a very "low privileged" user. Not as "you", not as "admin" - as a very low privileged user.
Ask your windows experts onsite how a service running as a low privileged user can get access to remote services
( i would suggest you don't get too carried away with this, this is not looking like a "robust" implementation, there are lots of real job scheduling tools out there -- enterprise manager for example, with error handling and so on)
mapping a network drive on windows within a procedure
Justin, February 10, 2005 - 4:30 pm UTC
Tom,
I am trying to map a network drive from within a stored proc.
Here is what I have done and what I get at the end:
1) Run these as sys
exec dbms_java.grant_permission('PHAME','java.io.FilePermission','C:\WINDOWS\system32\net.exe','execute');
exec dbms_java.grant_permission('PHAME','java.lang.RuntimePermission','*','writeFileDescriptor' );
2) run this as our schema owner
create or replace and compile
java source named "Util"
as
import java.io.*;
import java.lang.*;
public class Util extends Object
{
public static int RunThis(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;
}
}
}
/
3) run this as our schema owner
create or replace procedure call_net_use(p_cmd in varchar2)
as
x number;
begin
x := NET_USE(p_cmd);
end;
/
4) run this as our schema owner
exec call_net_use('net use j: \\servername\d$ password /user:domain\username');
( The net use command works at the command line of the database server (I have changed the parms to be generic))
I get:
java.security.AccessControlException: the Permission (java.io.FilePermission <<ALL FILES>> execute) has not been granted to PHAME. The PL/SQL to grant this is dbms_java.grant_permission( 'PHAME',
'SYS:java.io.FilePermission', '<<ALL FILES>>', 'execute' )
Do you see the problem?
Thanks very much!
February 11, 2005 - 7:44 pm UTC
sorry -- not even going to try to touch this one. network shares and stuff like that under windows is just plain "magic, especially when you involve an underprivileged service like the Oracle service"
services make everything a little different.
that command line test -- totally unrelated to the security/privilege environment the database is running as.
I'm thinking "you don't want to do this" -- really.
ok.. thanks for the input
Justin, February 14, 2005 - 9:58 am UTC
Works like a charm!!!
Deepak Haldiya, March 08, 2005 - 6:29 pm UTC
Hi Tom,
I have been using the code from this thread. It works great!!!
We have a tmp folder from which we want to delete all the files after certain operation.
When I use
exec :x := RUN_CMD('/usr/bin/rm /tmp/xyz.txt') ;
if works fine.
But what I really like to run is
exec :x := RUN_CMD('/usr/bin/rm /tmp/*.txt') ;
to delete all the files from the tmp foler. This does not work.
Any suggestions!!!
March 08, 2005 - 7:24 pm UTC
define "does not work"
Deepak Haldiya, March 09, 2005 - 10:49 am UTC
when I meant by "does not work" is that '/usr/bin/rm *.txt' passed as an argument to RUN_CMD does not delete a single file from /tmp folder. Although the procedure successfully completes and i do not get anything in DBMS JAVA OUTPUT.
If I pass the '/usr/bin/rm xyz.txt' then the procedure deletes the file from xyz.txt from the tmp folder.
Thanks
March 09, 2005 - 12:57 pm UTC
so, sounds like the * isn't getting expanded because it isn't going through a "shell" and the shell expands * and ?.
it tried to delete a file named "*.txt"
the safest solution is to not use * or ? -- for to fix this, we might have to use a shell script and that gets nasty (security wise)
See Erdal's link above
andrew, March 09, 2005 - 1:22 pm UTC
March 09, 2005 - 1:58 pm UTC
please -- consider the ramifications of /bin/sh access!!!!!
think about it, that is why I specifically say "safe" above.
(you want to give an Oracle shell to everyone? think of what can happen)
OS from Jave store procedure
Laxman Kondal, March 22, 2005 - 2:11 pm UTC
Hi Tom
I read you book and this page and wanted to create Java OS command to do export and landed up in many errors.
This one is the one I can not figure out and need your help.
Oracel 9R2 on Redhat Server2.1 and client from where I ran this Windows XP.
I search this page for dbms_java.grant_permission and unable to figure out my own mistake.
scott@TUNE> connect sys/xxxx@TUNE as sysdba;
Connected.
scott@TUNE> begin
2 dbms_java.revoke_permission
3 ('SCOTT',
4 'java.io.FilePermission',
5 '/opt/oracle/9.2.0.1.0/bin/exp',
6 'execute');
7
8 dbms_java.revoke_permission
9 ('SCOTT',
10 'java.lang.RuntimePermission',
11 '*',
12 'writeFileDescriptor' );
13 end;
14 /
PL/SQL procedure successfully completed.
scott@TUNE> rem show err
scott@TUNE> show err
No errors.
scott@TUNE> begin
2 dbms_java.grant_permission
3 ('SCOTT',
4 'java.io.FilePermission',
5 '/opt/oracle/9.2.0.1.0/bin/exp',
6 'execute');
7
8 dbms_java.grant_permission
9 ('SCOTT',
10 'java.lang.RuntimePermission',
11 '*',
12 'writeFileDescriptor' );
13 end;
14 /
PL/SQL procedure successfully completed.
scott@TUNE> show err
No errors.
scott@TUNE> connect scott/tiger@TUNE
Connected.
scott@TUNE> create or replace and compile
2 java source named "Util"
3 as
4 import java.io.*;
5 import java.lang.*;
6
7 public class Util extends Object
8 {
9 public static int RunThis(String args)
10 {
11 Runtime rt = Runtime.getRuntime();
12 int rc = -1;
13
14 try
15 {
16 Process p = rt.exec(args);
17
18 int bufSize = 4096;
19 BufferedInputStream bis =
20 new BufferedInputStream(p.getInputStream(), bufSize);
21 int len;
22 byte buffer[] = new byte[bufSize];
23
24 // Echo back what the program spit out
25 while ((len = bis.read(buffer, 0, bufSize)) != -1)
26 System.out.write(buffer, 0, len);
27
28 rc = p.waitFor();
29 }
30 catch (Exception e)
31 {
32 e.printStackTrace();
33 rc = -1;
34 }
35 finally
36 {
37 return rc;
38 }
39 }
40 }
41 /
Java created.
scott@TUNE> show err
No errors.
scott@TUNE> create or replace
2 function RUN_CMD( p_cmd in varchar2) return number
3 as
4 language java
5 name 'Util.RunThis(java.lang.String) return integer';
6 /
Function created.
scott@TUNE> show err
No errors.
scott@TUNE> create or replace procedure RC(p_cmd in varchar2)
2 as
3 x number;
4 begin
5 x := run_cmd(p_cmd);
6 end;
7 /
Procedure created.
scott@TUNE> show err
No errors.
scott@TUNE> create or replace procedure run_exp(p_exp_cmd varchar2)
2 is
3
4 l_exp_cmd varchar2(500);
5 l_return number := 0;
6
7 begin
8 --
9 l_return := run_cmd(p_exp_cmd);
10 --
11 if l_return = 0 then
12 dbms_output.put_line('Export session succeeded.');
13 else
14 dbms_output.put_line('Export session failed.');
15 end if;
16
17 exception
18 when others then
19 raise;
20 end run_exp;
21 /
Procedure created.
scott@TUNE> show err
No errors.
scott@TUNE> set serveroutput on size 1000000
scott@TUNE> exec dbms_java.set_output(1000000)
PL/SQL procedure successfully completed.
scott@TUNE>
scott@TUNE> exec run_exp('exp scott/tiger@TUNE, TABLES=(emp, dept), FILE=/tmp/exp_test.dmp, LOG=/tmp/exp_test.log');
java.security.AccessControlException: the Permission (java.io.FilePermission <<ALL FILES>> execute) has not been granted
to SCOTT. The PL/SQL to grant this is dbms_java.grant_permission( 'SCOTT', 'SYS:java.io.FilePermission', '<<ALL FILES>>', 'execute' )
at java.security.AccessControlContext.checkPermission(AccessControlContext.java)
at java.security.AccessController.checkPermission(AccessController.java)
at java.lang.SecurityManager.checkPermission(SecurityManager.java)
at oracle.aurora.rdbms.SecurityManagerImpl.checkPermission(SecurityManagerImpl.java)
at java.lang.SecurityManager.checkExec(SecurityManager.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at Util.RunThis(Util.java:13)
Export session failed.
PL/SQL procedure successfully completed.
scott@TUNE> show user
USER is "SCOTT"
scott@TUNE> begin
2 dbms_java.grant_permission
3 ('SCOTT',
4 'java.io.FilePermission',
5 '/opt/oracle/9.2.0.1.0/bin/exp',
6 'execute');
7
8 dbms_java.grant_permission
9 ('SCOTT',
10 'java.lang.RuntimePermission',
11 '*',
12 'writeFileDescriptor' );
13 end;
14 /
PL/SQL procedure successfully completed.
scott@TUNE> show err
No errors.
scott@TUNE> connect scott/tiger@tune
Connected.
scott@TUNE> set serveroutput on size 1000000
scott@TUNE> exec dbms_java.set_output(1000000)
PL/SQL procedure successfully completed.
scott@TUNE> exec run_exp('exp scott/tiger@TUNE, TABLES=(emp, dept), FILE=/tmp/exp_test.dmp, LOG=/tmp/exp_test.log');
java.security.AccessControlException: the Permission (java.io.FilePermission <<ALL FILES>> execute) has not been granted
to SCOTT. The PL/SQL to grant this is dbms_java.grant_permission( 'SCOTT', 'SYS:java.io.FilePermission', '<<ALL FILES>>', 'execute' )
at java.security.AccessControlContext.checkPermission(AccessControlContext.java)
at java.security.AccessController.checkPermission(AccessController.java)
at java.lang.SecurityManager.checkPermission(SecurityManager.java)
at oracle.aurora.rdbms.SecurityManagerImpl.checkPermission(SecurityManagerImpl.java)
at java.lang.SecurityManager.checkExec(SecurityManager.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at Util.RunThis(Util.java:13)
Export session failed.
PL/SQL procedure successfully completed.
scott@TUNE> select * from dba_java_policy where grantee = 'SCOTT';
KIND GRANT TYPE_SCHEM TYPE_NAME NAME ACTION ENABLED SEQ
-------- ----- ---------- ---------------------- ------------------------- --------------- -------- ---
GRANT SCOTT SYS java.io.FilePermission /opt/oracle/9.2.0.1.0/bin execute ENABLED 75
/exp
GRANT SCOTT SYS java.io.FilePermission /usr/bin/exp execute ENABLED 77
GRANT SCOTT SYS java.lang.RuntimePermi * writeFileDescri ENABLED 76
ssion ptor
GRANT SCOTT SYS java.lang.RuntimePermi /tmp/ writeFileDescri ENABLED 79
ssion ptor
4 rows selected.
scott@TUNE>
What I am doing wrong is obviously I can not find.
Thanks for all the help.
Regards.
March 22, 2005 - 6:05 pm UTC
you gave privs to run
/x/y/z
and ran
z
/z/y/z <> z
OS Command from Java Pl Sql
Laxman Kondal, March 22, 2005 - 2:52 pm UTC
Hi Tom
This was my first Java program and one mistakle I found was that path was not correct and then reconnected and worked fine.
begin
dbms_java.grant_permission
('SCOTT',
'java.io.FilePermission',
'/opt/oracle/product/9.2.0.1.0/bin/exp',
'execute');
dbms_java.grant_permission
('SCOTT',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
end;
I orginally missed /product/ in path.
I will appriciate if you could help me to make it better or your any suggestion.
Thanks
Regards.
March 22, 2005 - 6:07 pm UTC
well, it was mostly the orginal code from above, so I think I like it...
OS Command from Pl Sql
Laxman Kondal, March 22, 2005 - 9:04 pm UTC
Hi Tom
Thanks for reply. I have few ....
In one of your follow-up you said
"did you use dbms_java grant permission to grant yourself the needed privs? like my example does?"
If sys as sysdba has granted 'java.lang.RuntimePermission', and execute permission then why do I need to grant it to me again?
Is it required for all users to grant permission to ownself?
After granting privs whats the reason for reconnecting again to execute? Java cannot see those grant/prives?
Once JAVA SOURCE NAMED "Util" is compiled where can I find compiled code in oracle?
I could not find dbms_java.grant_permission on any document, where is it?
Thanks for you help and wonderful source of knowledge.
Regards.
March 23, 2005 - 1:13 am UTC
accessing xml file in OS filesystem
A Reader, March 31, 2005 - 6:28 am UTC
I am trying to use a java stored procedure in solaris environment. The java code is accessing a xml file and inserts the data within it into a table in oracle. I am using java.io.File class to create the file object. I am not able to create the file object using following code.
InputSource input = new InputSource(new FileReader(new File("/export/home/stniitd1/interface/inbound/a55progsched/a55_episode_sample.xml")));
when I used System.getProperty("user.dir"), I got following string
/nas/orasoft/baracuda/product/9.2.0/
March 31, 2005 - 8:06 am UTC
why aren't you able to create the file object (i have as much information as you would if I said to you "my car won't start, why")
Java Source
Stefan Knecht, April 07, 2005 - 8:59 am UTC
Hello Tom,
i implemented the java code you've shown above, and it works great.
however, when i tried to modify it slightly to this:
CREATE OR REPLACE AND COMPILE JAVA SOURCE named "Util_zip"
as
import java.io.*;
import java.lang.*;
public class Util_zip extends Object
{
public static int RunThis(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);
#sql {
CALL scanning.insert_file (:buffer) };
rc = p.waitFor();
}
catch (Exception e)
{
e.printStackTrace();
rc = -1;
}
finally
{
return rc;
}
}
}
/
show errors;
oracle throws 01461, 00000, "can bind a LONG value only for insert into a LONG column".
as the byte[] apparently maps to a LONG RAW (?). What i am trying to do is insert the data that the unix command spits back out into a table for later processing.
The procedure being called is very straight forward:
PROCEDURE insert_file (p_file IN VARCHAR2)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO ziplist (file_name) VALUES (p_file);
COMMIT;
END;
i use autonomous_transaction pragma, because this whole thing is being called inside a function. the data integrity should be fine, though as there's no concurrent accesses to this table at all.
The operating system command being called is also working fine, it's a simple shell script that does:
#!/bin/sh
/usr/local/bin/unzip -l $1 | /bin/awk '{ print $4 }' | /bin/grep '\.'
i tried to "fix" the above java to convert this to a datatype oracle would understand, but after 2h of failures (i know enough java to read the source and java.sun.com, but that's not enough anymore here :| ) ... i am hoping you might be able to tell me how to adjust the source to accomplish this task. or maybe you even see a much easier way to do the same trick.
looking forward to your reply, and thanks in advance
Stefan
April 07, 2005 - 10:46 am UTC
why wouldn't you use a blob/clob and just stream it right in there in the java?
Error
Andy, April 07, 2005 - 1:09 pm UTC
Hi Tom, I try use this example but when i execute the procedure rc, failure
SQL> exec rc('ls')
java.lang.ArrayIndexOutOfBoundsException
at Util.RunThis(UTIL.java:15)
I see the other questions about the error java.lang.ArrayIndexOutOfBoundsException, but all have UTIL.java:14 and for me show UTIL.java.15 (change the number)
It's the same error!?
Thank's
April 07, 2005 - 1:33 pm UTC
yes
Excellent Example
Charlie, April 07, 2005 - 2:50 pm UTC
Out of all the examples of java calling a host command - this one has to be the best. I needed to use logic like this and it works great.
Permission Error
Andy, April 07, 2005 - 6:17 pm UTC
hi Tom again
When i try execute the RUN_CMD function, show me the next error:
B@db9i> exec :x := RUN_CMD('/usr/lib ls')
java.security.AccessControlException: the Permission (java.io.FilePermission /usr/lib execute) has
not been granted to HT. The PL/SQL to grant this is dbms_java.grant_permission( 'HT',
'SYS:java.io.FilePermission', '/usr/lib', 'execute' )
at java.security.AccessControlContext.checkPermission(AccessControlContext.java)
at java.security.AccessController.checkPermission(AccessController.java)
at java.lang.SecurityManager.checkPermission(SecurityManager.java)
at oracle.aurora.rdbms.SecurityManagerImpl.checkPermission(SecurityManagerImpl.java)
at java.lang.SecurityManager.checkExec(SecurityManager.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at Util.RunThis(UTIL.java:13)
I saw the solution for this error: use 2 users, User A give the grants to user B and user B create all the programns (Util,RUN_CMD, RC).
But show me the same error!!! please help me!!
I tryed use SYS user for give grants too
April 07, 2005 - 7:06 pm UTC
did you read the error message? it actually shows you the permission you need.
but....
/usr/lib ls
what is that?
In that context, /usr/lib would be a program (but it isn't) and ls would be a parameter to it.
perhaps you meant to try and run something else?
Permission Error - Ok
Andy, April 07, 2005 - 6:52 pm UTC
forgets the previous question, already arrange it...
thanks
But what is the called script able to DO?
Tom Best, April 18, 2005 - 10:03 am UTC
Tom:
This is great for us - we need to call a script from pl/sql, and the external proc thing was giving us trouble. This is cleaner.
One question though - I can get a script to run, such as:
echo Hello world.
But... if the script does something to a file - or creates a directory or anything - I see the echo output, but the file operation does not actually happen.
E.G.
echo Hello World
mv /home/oracle/this /home/oracle/that
I see Hello World (so I know it ran) but file "this" does not become "that".
Is this a permissions thing? Do I need a DIRECTORY object created and have perms on it or something?
Thanks.
April 18, 2005 - 10:23 am UTC
mv is a command, might not be in your path. echo might have been.
but can surely be a permission issue, the script is running as the dedicated server userid in the OS. It can only do what that user can do.
Try this,
/bin/touch /tmp/testing
and make sure that /tmp/testing doesn't exist first, if it creates a file, it'll show you "who" you are.
It was the path
Tom Best, April 18, 2005 - 2:00 pm UTC
That fixed it. It was the path. The user was indeed oracle, but the path was not setup in the script.
Thanks again.
Execute command at client side(Windows XP)
Morg, April 27, 2005 - 3:03 pm UTC
Dear Tom,
I want from client side (Windows XP,Plus80w) to execute a dos command like (Copy file) using PL/SQL and kindly note that client connect to database 9i on unix server.
April 27, 2005 - 3:23 pm UTC
not going to happen.
PLSQL runs on the server, not on the client (unless you are running forms but even then it is running in the middle tier).
sqlplus can run a host command on the client. but plsql cannot.
Calling exp/imp from java
Laxman Kondal, May 19, 2005 - 5:54 pm UTC
Hi Tom
I need your help to solve this export/import from java class which I got from this site. It works fine and its realy great and when I wanted to test it with wrong username/password hangs, waitng for username/password.
Since I am calling from pl/sql there is no way I can kill this.
Could you please help me to figure out how to fix this.
Thanks
May 20, 2005 - 7:07 am UTC
kill it at the OS level (and then understand what a mistake this could be -- calling a program that tries to interact with a user....)
Calling exp/imp from java
Laxman Kondal, May 20, 2005 - 7:12 am UTC
Hi Tom
Thanks for reply.
We did kill it from OS but I was trying to find if any way java code can be alterd to cater for this eventually.
Anoter alternate was to hard code username/pwd which may not be desirable.
Thanks and regards.
May 20, 2005 - 8:08 am UTC
only host out to things that will NEVER interact with the end user.
off topic ...
Paul, May 20, 2005 - 10:41 am UTC
Tom - what's going on today? The 'last updated'for 20 May 2005 8am appears on one line for questions 1 to 10, and straddles 2 lines for questions 11 to 20?
May 20, 2005 - 6:26 pm UTC
changed nothing, window width perhaps on your screen?
print to file
rye, May 20, 2005 - 12:27 pm UTC
hi tom,
execellent stuff. what i'm trying to do is execute a .bat file that calls a vbscript that prints a ms word doc to pdf. everything works great from the commandline. when i try and run it using your proc, the word doc opens and gets sent to the pdf writer, but hangs there. in other tests, i have been able to sucessfully print to a regular printer using the proc. any ideas on what could be preventing me from printing using the pdf writer?
May 20, 2005 - 6:36 pm UTC
windows...
the database is running in a different environment -- it doesn't have your "printers", "shares" etc - it has IT'S set up --
it is running as a service, you'll need to find a windows guy to help you get a service to know about other stuff like that.
Any addvice on remote progam calls?
Rene, May 30, 2005 - 5:39 am UTC
The initial solution is very cool! But what would I do, if I have to call a binary on a different server, that is not running an Oracle database? (Otherwise I could call a procedure on the remote oracle server, which then calls the program locally....)
The company's policy is to not allow anything else on the Oracle server (which is okay with me).
The environment is Oracle 9i (9.2.0.6.0) on Windows 2000 Server.
The "remote" program is on a different Windows 2000 Server.
So, how can I call a program that is on a different server in this environment?
Do you have any ideas or hints (it seems to be a windows specific problem) how do I do a "remote call" from the Oracle database to the other server?
Sincerly, Rene
May 30, 2005 - 9:05 am UTC
You'll have to ask your system and security folk (remote program execution can be very "virus like").
Say the remote machine has an application server, you could invoke it via a URL (utl_http).
Say the remote machine has no security, you could use some windows command line to to a remote program execution.
But this is something you need to solve "outside" of Oracle first. Just make it so this database server can run that remote program. Once you figure that out given you OS's, your security, your setup , we can proceed from there.
host call fails on Linux 10.1.0.3/10.1.0.4
Pete, June 07, 2005 - 10:20 pm UTC
Tom,
I've used the Util class since ver 817 ->10.1.0.2 with no issue at all.
When running same code after the upgrade I'm getting
ERROR:
ORA-03114: not connected to ORACLE
BEGIN rc('/bin/ps -ef'); END;
*
ERROR at line 1:
ORA-03113: end-of-file on communication channel
No trace files to find in udump/bdump. I also tried putting dbms_output and java system.out.. but the connection aborts and never finishes and I'm not getting any debug info at all.
In addition to the specific grants I've also granted javauserpriv, javasyspriv but no different result.
Is anyone aware of anything that has changed in the ojvm that makes this non backward compatible ?
exec dbms_java.grant_permission('IRIS', 'java.io.FilePermission', '/bin/ps','execute');
exec dbms_java.grant_permission('IRIS', 'java.io.FilePermission', '*','read,write');
create or replace and compile
java source named "Util"
as
import java.io.*;
import java.lang.*;
public class Util extends Object
{
public static int RunThis(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;
}
}
}
/
create or replace
function RUN_CMD( p_cmd in varchar2) return number
as
language java
name 'Util.RunThis(java.lang.String) return integer';
/
create or replace procedure RC(p_cmd in varchar2)
as
x number;
begin
x := run_cmd(p_cmd);
end;
/
set serveroutput on size 10000
exec dbms_java.set_output(1000)
exec rc('/bin/ps -ef');
June 08, 2005 - 8:17 am UTC
not sure on the 3114, I cannot reproduce that at all.
but in 9i and 10g for me -- I had to wrap the ps call in a script to get the environment set up properly.
Have you checked the execution environment (eg: run /bin/env instead?)
Connected to:
Oracle Database 10g Enterprise Edition Release 10.1.0.4.0 - Production
With the Partitioning, OLAP and Data Mining options
worked straight away for me.
Further investigation of ORA-3113
Pete, June 08, 2005 - 1:31 pm UTC
To further narrow down the issue - I created a new user and granted as sys
EXECUTE dbms_java.grant_permission( 'HST60','SYS:java.io.FilePermission','<<ALL FILES>>','execute');
EXECUTE dbms_java.grant_permission( 'HST60','SYS:java.io.FilePermission','*','read,write');
EXECUTE dbms_java.grant_permission( 'HST60','SYS:java.lang.RuntimePermission','writeFileDescriptor','*' );
EXECUTE dbms_java.grant_permission( 'HST60','SYS:java.lang.RuntimePermission','readFileDescriptor','*' );
Next I created the class and stored procs using above code
To verify that the host call gets executed I did:
SQL> set serveroutput on size 10000
exec dbms_java.set_output(1000)
exec rc('/bin/env');SQL>
PL/SQL procedure successfully completed.
SQL>
java.io.IOException: can't exec: /bin/env doesn't exist
-ok my host call is attempted - I then proceeded with
Oracle Database 10g Enterprise Edition Release 10.1.0.3.0 - Production
With the Partitioning, OLAP and Data Mining options
SQL> set serveroutput on size 10000
exec dbms_java.set_output(1000)
exec rc('/usr/bin/env');SQL>
PL/SQL procedure successfully completed.
SQL>
ERROR:
ORA-03114: not connected to ORACLE
BEGIN rc('/usr/bin/env'); END;
*
ERROR at line 1:
ORA-03113: end-of-file on communication channel
SQL> !/usr/bin/env
LESSKEY=/etc/lesskey.bin
MANPATH=/usr/local/man:/usr/share/man:/usr/X11R6/man:/opt/gnome/share/man
INFODIR=/usr/local/info:/usr/share/info:/usr/info
NNTPSERVER=news
Script without environment fails
I then tried a script that sets environment and then executes
SQL> set serveroutput on size 10000
exec dbms_java.set_output(1000)
exec rc('/opt/iris/bin/shell.sh /usr/bin/env');SQL>
PL/SQL procedure successfully completed.
SQL>
ERROR:
ORA-03114: not connected to ORACLE
BEGIN rc('/opt/iris/bin/shell.sh /usr/bin/env'); END;
*
ERROR at line 1:
ORA-03113: end-of-file on communication channel
Shell.sh - I noted that the file hallo didn't get created
oracle@risqube:~> more /opt/iris/bin/shell.sh
#!/bin/sh
PATH=${PATH}:/opt/iris/bin:/bin:/usr/bin
export PATH
system "echo hallo >/opt/iris/log/hallo";
eval $*
java_pool_size 64M
large_pool_size 16M
I was thinking that maybe the java parameters could affect this but the fact that the db is running java stored procedures and javamail just fine so the ojvm is working - there are no invalid classes - the host call is the problem - Any ideas to troubleshoot this much appreciated
Many Thanks
Pete
June 08, 2005 - 1:49 pm UTC
you'll want to work with support, they can help you set events to create trace information and debug this.
Executing shell scripts and passing parameters to
Azmat, June 26, 2005 - 12:45 pm UTC
Tom,
I have a shell script which accepts two parameters and creates a text file, this works good on unix environment. I need to call this scripts from PL/SQL environment so that I can store the generated file in a BLOB column and later display it on browser. How would I do it? Here is my shell call in unix environment.
$ itg.sh -a P -b 10 -out abc.txt
where itg.sh is a shell script, P and 10 are the two parameters value for -a and -b respectively and -out is is used for out parameter and result is abc.txt file. I want to store this text file on a BLOB column to display it on browser?
Thank you
June 26, 2005 - 1:55 pm UTC
you want to store text in a clob.
but, this page shows you how to run a shell script from plsql and then dbms_lob.loadfromfile will be useful to get the generated text file into the database.
But, if you just want to display it on the browser, you could also just use a BFILE instead of a lob in the database -- if the data is not going to persist for any duration of time.
executing shell script from DB
Azmat, June 26, 2005 - 11:00 pm UTC
Actually, I meant to ask if I can use following procedure ( created in this thred earlier) to run my shell script.
sql>exec run_exp('itg.sh -a P -b 10 -out abc.txt');
I am not sure if this will run or not. I wanted to be sure about this before asking all the permission ( dbms_java.grant_permission) from our DB group.
Thank you
June 27, 2005 - 7:02 am UTC
yes, you can run shell scripts.
RE: mapping a network drive on windows within a procedure
Edgar, June 27, 2005 - 2:47 am UTC
Hi,
Oracle by default on Windows run as service under LOCAL_SYSTEM account.
Because of Windows security features, LOCAL_SYSTEM is prohibited to USE network mapped drives.
Because of that, for example, you cannot use RMAN to disk-to-disk backup to network mapped drive, you cannot set ARCHIVE_LOG_DEST_n to network mapped drive.
There is a workaround (i find on Metalink) : you can change ownership of Oracle services (database, listener) to someone another user account (Administrator).
I don't remember Note #.
OS cp command
Laxman Kondal, July 15, 2005 - 3:29 pm UTC
Hi Tom
I have used run_cmd function for exp, imp and sqlldr and this 'cp' command I need your help please to work.
SQL> exec :x := run_cmd('cp /tmp/exh_hi.dmp /tmp/exp_hi_1.dmp')
PL/SQL procedure successfully completed.
X
----------
-1
SQL>
This is the permission granted as sys
begin
dbms_java.grant_permission
('OPO_USER',
'java.io.FilePermission',
'/bin/cp',
'execute');
dbms_java.grant_permission
('OPO_USER',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
end;
/
I used different files to copy .dmp, .txt, and .log - all in /tmp/ but all exit codes are -1.
What's I am missing or doing something wrong.
Thanks and regards.
July 15, 2005 - 6:17 pm UTC
/bin/cp <> cp
OS cp command
Laxman Kondal, July 15, 2005 - 11:43 pm UTC
Hi Tom
Thanks for reply.
I am not sure about '/bin/cp <> cp' it should be in dbms_java.grant_permission and is it reqire to have '<>' for all os command?
Thanks and regards
July 16, 2005 - 9:16 am UTC
/bin/cp is not the same text as cp
cp might resolve to /usr/bin/cp or /home/badguy/cp or whatever
if you grant permission on /bin/cp, then you need to run /bin/cp.
And you should grant on /bin/cp, not just cp, so you know the right cp is being used and not a trojan horse cp.
What bout timeout
Denis, July 27, 2005 - 6:29 pm UTC
Tom, if I run some command and it is hanging, it would be very helpfull to be able to set timeout. Could you advice how to do it?
I need to run "scp" command on windows to transfer files between servers using public and private keys. I need to cache the key under account oracle is running. What is Windows account name oracle is running under?
July 27, 2005 - 8:41 pm UTC
commands typically do not "hang", they are doing something that takes a long time (AND it takes even longer in general to "undo" what they did).
Some things like waiting for a row to lock it can be waited for (for update wait <n>) but you program that into the transaction.
No idea what "scp" is - but you pick the service attributes for Oracle, you pick who it runs as if you want. If you are using 10g, you can look at dbms_file_transfer to move files between Oracle instances. But look at your service and see what it is set to run as.
timeout
Denis, July 28, 2005 - 2:40 pm UTC
Tom,
For example, I call command which loads data from table to flat file using sqlplus (</code>
http://asktom.oracle.com/~tkyte/flat/index.html <code>. If I put there wrong filename and run manuallly from console, I will get an error message. If I run it from pl/sql using this java class, it will hang. is there any kind of timeout solution?
July 28, 2005 - 3:44 pm UTC
You must be excessively careful when calling interactive programs from any environment that isn't interactive though. Period.
but you could change the java class to poll for output instead of block on output if you like and time out - but then you have that nasty problem of "that thing is still out there" to deal with.
Best to ensure whatever you call is NOT interactive under any circumstances.
Hang or not to hang
Marcelo, July 28, 2005 - 8:17 pm UTC
Extracted from the comment above...
/quote
commands typically do not "hang", they are doing something that takes a long time (AND it takes even longer in general to "undo" what they did).
/quote
At the point of view of the database, it is true. But when running something in Windows it can (and surely will) hang. And I believe in this case the OS is really doing something, but that will never finish :)
July 29, 2005 - 8:18 am UTC
I was thinking of commands in the sense of a sql command. But, you are free to rewrite the java stored procedure in a polling fashion -- it is just code, you can in fact make it do whatever you like!
timeout and errors
Denis, July 28, 2005 - 9:34 pm UTC
Tom, maybe then in this case using DBMS_SCHEDULER is better idea? If it command fails, job fails. Nothing is hanging.
From other hand I tried to incorporate timeout into your code
and put this inside try block:
if (timeout > 0) {
Thread destroyProcess = new Thread() {
public void run() {
try {
sleep(timeout);
} catch (InterruptedException ie) {
} finally {
p.destroy();
}
}
};
destroyProcess.start();
}
But started getting interesting behavior. If my commands where correct, command did succeded but I got an error(below). if command is incorrect, I was getting the same error right away:
ORA-29516: Aurora assertion failure: Assertion failure at sjonio.c:128
WaitForMultipleObjects failed: errno = 6
Maybe we can't do timeout because java in oracle PL/SQL is single-threaded?
But even in case we don't need timeout, when we get error message right way, It is strange not to be able to through an error from Java (stop process and return -1) , if command failed. SQL server has similar functionality CMDSHELL extended stored procedure. But it throughs en error in case command is incorrect.
So using your code PL/SQL will always hang if command through an error? Right?
Thanks
July 29, 2005 - 8:22 am UTC
the problem is, the job would hang forever.
They have a command running that is waiting for the user to hit the enter key.
The user never will hit the enter key.
The job will be stuck forever.
POLL for data, don't do anything that blocks.
Trouble Executing Shell Script
TH, August 03, 2005 - 11:33 am UTC
Hey Tom
Thanks so much for this script. I think its going to change the way we do Data Warehousing forever because we can now do all of the things that we need to do from our Oracle packages.
One thing I have yet to figure out, is how to automate decryption of files using gpg. I have a script that automatically decrypts all the files in the same folder as the script. I can run the sh script that we have from a prompt, and it works fine, but when I run it via the procedure RC - it completes successfully, but does not actually execute the file. The return value is 127.
Any ideas?
August 03, 2005 - 12:06 pm UTC
well, if you are going to automate the decryption of something like this, one wonders why they are encrypted in the first place.
put debug into the script -- 999 times out of 1000 it is an environment issue. printout your environment, echo commands, redirect it to a "trace" file in tmp
Actually....
TH, August 03, 2005 - 2:34 pm UTC
I was wondering what the return value from the java means. I looked up the WaitFor() method, and it looks like is pauses the process, waiting for the thread to finish, and then kills it. It says that a return of 0 is normal. Anything other than that is not. What does the number that it returns represent?
As for why we are trying to automate encryption - the encryption is only to get the file from an outside source into our network.
Thanks!
August 03, 2005 - 5:57 pm UTC
I guess it means "not normal", it should probably be the return code from the shell script.
time to add debug to it! almost always an environment issue (bad path, missing something). remember the script runs in a "pristine, different, ORACLE environment separate from yours"
Still stumped....
TH, August 04, 2005 - 3:36 pm UTC
Tom - You can preface your response with how sick of me you are - i wont be offended. Im sick of me on this issue too.
I have a .sh file that runs to decrypt some files automatically. The problem is that the gpg binary is in a different directory, and even if I give the absolute path of the dir, it still does not work -- so the .sh looks like this...
!#/bin/sh
cd /stage/incoming
/usr/local/bin/gpg --decrypt-files *.pgp
exit
I know that the problem here is ennvironment, but I cannot figure out what to do to rectify it. I have had the Unix guys look at this and do everything they can to rule out an environment issue. I just dont know enough about Unix to know what to do next. I think the problem has to do with the gpg residing in a different directory than the files I want to decrypt.
August 04, 2005 - 8:40 pm UTC
does gpg have a "verbose mode"
do you know how to redirect stdout AND stderr to a tmp file (capture any and all output from gpg)
oh, and how does gpg work? where does it get the encryption keys from? how does it know where to find them?
calling Java program from PL/SQL.
Rajesh, August 22, 2005 - 10:18 am UTC
I want to call a java program from my pl/sql block. When I wrote a small program like this
create or replace and compile
java source named "Util"
as
public class Util {
public static String hi() {
System.out.println ("tracing here");
return "hello there";
}
}
the following error occured. Why? what can be the cause. I am using oracle 9i. Please help me!!!!
ERROR at line 2:
ORA-00600: internal error code, arguments: [KSMASG1], [4032], [4032], [], [],
[], [], []
August 23, 2005 - 3:58 am UTC
ora-600 always means "please contact support"
ops$tkyte@ORA9IR2> create or replace and compile
2 java source named "Util"
3 as
4 public class Util {
5 public static String hi() {
6 System.out.println ("tracing here");
7
}
7 return "hello there";
8 }
9 }
10 /
Java created.
especially since it doesn't reproduce universally
dave, August 23, 2005 - 6:29 am UTC
take a look at metalink note 4014485.8
Looks like this could be for you
calling Java programs from PL/SQL
Rajesh, August 23, 2005 - 8:24 am UTC
Thank You very much. Java package was not installed initially. After installation it worked.
Java Program from PL/SQL
Rajesh, August 24, 2005 - 5:21 am UTC
I am importing these class files in my Java program.
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.openssl.PEMReader;
import java.security.interfaces.RSAPrivateKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.provider.JCERSAPublicKey;
The code is working in Windows NT in java compiler.
My intention is to create a java source for this in oracle. So that i can access the methods described in the java program. which runs in unix box.
I have set the class path in unix box like this
export CLASSPATH=$CLASSPATH:$HOME/bcmail-jdk13-129.jar:$HOME/bcpg-jdk13-129
But I am getting error like this...
Class org.apache.commons.codec.binary.Base64 not
found in import.
0/0 Encropt:8: Class org.apache.commons.codec.binary.Hex not found
in import.
0/0 Encropt:9: Class org.bouncycastle.openssl.PEMReader not found in
import.
0/0 Encropt:11: Class
org.bouncycastle.jce.provider.BouncyCastleProvider not found in
LINE/COL ERROR
-------- -----------------------------------------------------------------
import.
0/0 Encropt:12: Class org.bouncycastle.jce.provider.JCERSAPublicKey
not found in import.
0/0 Info: 5 errors
What is the problem here? Is it the problem with my classpath settings. I opened the jar file in winzip and searched for the class files. the class files are there.
August 24, 2005 - 10:57 am UTC
you have to load the jars into the database, your classpath isn't relevant, everything must be contained within the database.
Loved it as always
Dmitriy N., September 06, 2005 - 5:33 pm UTC
I found exactly what I needed
Error: The handle is invalid.
Raman, September 07, 2005 - 3:08 pm UTC
Hello Tim,
When I run this small program for testing .... get this error:
SET SERVEROUTPUT ON SIZE 1000000
CALL DBMS_JAVA.SET_OUTPUT(1000000);
BEGIN
Host_Command (h_command => 'move C:\apr.txt D:\apr.txt');
END;
/
The handle is invalid.
PL/SQL procedure successfully completed.
What would be your suggetion ?? Any clue ??
regards,
-Raman
September 07, 2005 - 3:44 pm UTC
that would not be the full error stack would it.
Raman, September 07, 2005 - 3:55 pm UTC
This is the only error I get it ... At first I used to think, there's something wrong in my procedure where I used HOST command ... after debugging I found out that Java procedure is causing the error:
I have re-created every thing :
- Created Java Procedure
- PL/SQL wrapper
- Granted Privileges
EXEC Dbms_Java.Grant_Permission('SCHEMA-NAME', 'java.io.FilePermission', '<>', 'read ,write, execute, delete');
EXEC Dbms_Java.Grant_Permission('SCHEMA-NAME', 'SYS:java.lang.RuntimePermission', 'writeFileDescriptor', '');
EXEC Dbms_Java.Grant_Permission('SCHEMA-NAME', 'SYS:java.lang.RuntimePermission', 'readFileDescriptor', '');
- Tested it.
Could you please suggest me what to do to get rid of this error:
thanks.
September 07, 2005 - 7:34 pm UTC
no, because that error would not appear all by itself like that.
make a small 100% complete test case for us to look at.
Raman, September 09, 2005 - 12:04 am UTC
I had to run 'rmjvm.sql' and 'initjvm.sql' scripts ....
With companion CD, got rid of 'JAccelerator' error ...
Finally it works ....
thanks.
Command not executed
Mody, September 21, 2005 - 4:30 am UTC
Dear Tom,
I have create file mk in folder /home/oracle ,this file contains one line (mkdir /home/oracle/test),
then I use you example with some small modifications ,
the procedure runs well but the directory isn't created.
begin
dbms_java.grant_permission
('MKT',
'java.io.FilePermission',
'/home/oracle/mk',
'execute');
dbms_java.grant_permission
('MKT',
'java.io.FilePermission',
'/home/oracle/mk',
'execute');
dbms_java.grant_permission
('MKT',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
end;
/
create or replace and compile
java source named "Util"
as
import java.io.*;
import java.lang.*;
public class Util extends Object
{
public static int RunThis(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)
{
System.out.println("exception ya man");
e.printStackTrace();
rc = -2;
}
finally
{
return rc;
}
}
}
/
create or replace
function RUN_CMD( p_cmd in varchar2) return number
as
language java
name 'Util.RunThis(java.lang.String) return integer';
/
create or replace procedure RC(p_cmd in varchar2)
as
x number;
begin
x := run_cmd(p_cmd);
end;
/
set serveroutput on size 1000000
exec dbms_java.set_output(1000000)
exec rc('/home/oracle/mk');
September 21, 2005 - 7:11 pm UTC
likely a path problem.
mkdir is a "program"
so, is mkdir in the path of the oracle dedicated servers environment (best for security and because of this to be explicit -- /path/to/mkdir
and make sure the script starts with #!/bin/sh or whatever.
Run a Oracle Report through pl-sql
Nikhilesh, October 05, 2005 - 1:05 am UTC
Dear Tom,
I'm trying to run a Oracle Report from pl-sql(the report generates a .pdf file to a specific location).
Using java I'm able to run the commands like ps and ls but I'm not able to run rwclient.sh. I fact I want to run
exec rc('/u01/app/oracle/product/dev/bin/rwclient.sh server=myserver report=/export/home/myhome/my_rep.rdf userid=my_user/my_password@my_service desformat=pdf destype=file desname=/export/home/my_home/name/test.pdf')
Is it possible?? Should I keep on trying??
Please mention what will be the privileges I will require to run this.
Thanks a lot in advance........
October 05, 2005 - 7:11 am UTC
remember, the environment is "different" here - you might create a script that dumps the environment using '/bin/env' or whatever (use full qualified commands - you don't even know what the PATH is)
set all environment variables EXPLICITLY
and make sure the script starts with
#!/bin/shellname
if you read through this page - we've discussed this times before - you can run scripts.
What permissions are required??
Nikhilesh, October 06, 2005 - 12:59 am UTC
Dear Tom,
Thanks for your reply. Yesterday I could generate the report running script file through pl-sql. And as you said before running that I had run one extra script file which sets the environment before generating .pdf file report.
But the problem is I have granted read permission (using dbms_java.grant_permission)to all the files i.e. script and .rdf.
Now I want to know Do we need to grant the permission to the script file we are running or to all of the script files and the .rdf files we are using in the main script file?? Will this method be secure??
October 06, 2005 - 7:44 am UTC
you do not need the grants to read all of that, once the script is running, it is quite out of our control what you can and cannot access - the operating system is in charge at that point.
you only need to permissions to run the script.
A reader, October 06, 2005 - 1:17 pm UTC
If we want to send the control to background ( like & in unix) by using dbms_job.submit(a, 'RC(something);') ,
Do we have any way to check the value of X varibale to see the run_cmd(p_cmd) is successfull or not?
create or replace procedure RC(p_cmd in varchar2)
as
x number;
begin
x := run_cmd(p_cmd);
end;
October 06, 2005 - 1:46 pm UTC
sure, if the job you submit, that runs in the background were to notify you someway after the job completed (wrote a row into a table for example....)
A reader, October 11, 2005 - 6:29 pm UTC
To,
We just migrated our database from solaris to Linux. We had few java stored procedure (mostly copy from your site -like reading files from directory etc..). Suddenly it stops working in linux. Also I have notied that we have to grant permission on specifice file and directory permission is not working (java.io.FilePermission). for eg. if i have want to read file on /user/bin/ directory then i have grant permission on the file. directory permission is not working. Could you please help us.
note - We exported database from solaris and impored it into linux os using oracle export and import.
Do we have to recreate JVM? ie do we have to run
/javavm/install/rmjvm.sql
/javavm/install/initjvm.sql
again ?
appreciate any help
thanks
October 12, 2005 - 7:06 am UTC
examples? (i developed almost all of my examples on linux in the first place)
did you also happen to change *versions* of the database whilst doing this?
A reader, October 11, 2005 - 6:47 pm UTC
To,
We just migrated our database from solaris to Linux. We had few java stored procedure (mostly copy from your site -like reading files from directory etc..). Suddenly it stops working in linux. Also I have notied that we have to grant permission on specifice file and directory permission is not working (java.io.FilePermission). for eg. if i have want to read file on /user/bin/ directory then i have grant permission on the file. directory permission is not working. Could you please help us.
note - We exported database from solaris and impored it into linux os using oracle export and import.
Do we have to recreate JVM? ie do we have to run
/javavm/install/rmjvm.sql
/javavm/install/initjvm.sql
again ?
appreciate any help
thanks
A reader, October 12, 2005 - 9:32 am UTC
Hi Tom,
We upgraded our database from 8.1.7.4 to 9.2.0.6.
getting following errors
java.security.AccessControlException: the Permission (java.io.FilePermission /nfsprod2/mkt read) has not been granted to SBLINT. The PL/SQL to grant this is dbms_java.grant_permission( 'SBLINT', 'SYS:java.io.FilePermission', '/nfsprod2/mkt', 'read' )
at java.security.AccessControlContext.checkPermission(AccessControlContext.java)
at java.security.AccessController.checkPermission(AccessController.java)
at java.lang.SecurityManager.checkPermission(SecurityManager.java)
at oracle.aurora.rdbms.SecurityManagerImpl.checkPermission(SecurityManagerImpl.java)
at java.lang.SecurityManager.checkRead(SecurityManager.java)
at oracle.aurora.rdbms.SecurityManagerImpl.checkRead(SecurityManagerImpl.java)
at java.io.File.list(File.java)
at java.io.File.listFiles(File.java)
at DirListName.getDirList(DirListName.java:8)
we are reading file (test.txt) from '/nfsprod2/mkt' dir and we have already granted this permisson
dbms_java.grant_permission( 'SBLINT', 'SYS:java.io.FilePermission', '/nfsprod2/mkt', 'read' )
Do I have do
dbms_java.grant_permission( 'SBLINT', 'SYS:java.io.FilePermission', '/nfsprod2/mkt/*', 'read' ) to select all files ??
Thanks
October 12, 2005 - 1:54 pm UTC
can you show me
a) you doing the grant
b) reconnecting
c) running the procedure and getting the failure
as a cut and paste from sqlplus
Is there a problem with this in version 10.1.0.3 ?
Holger Schweichler, October 14, 2005 - 10:55 am UTC
Hello Tom,
I've been struggling with running ksh scripts from PL/SQL using java for a couple of days now (already opened a TAR on this issue and uploaded the class and test script we're using, but it couldn't be reproduced by your colleagues so far while I see the same behaviour on 3 instances). Do you know of any issues in 10.1.0.3 when calling a shell script and passing some parameters? It works fine with some combinations, but returns a 255 on others (which is bogus because the ksh script is where it belongs and permissions are set correct, otherwise it won't work when calling the ksh with different parameters).
I went through this thread now and verified just the same behavior occurs when I use your example class/function/procedure... so the problem seems to be really a general one.
I will upgrade one instance to 10.1.0.4 this weekend and see if it still happens (since support couldn't reproduce on either 10.1.0.2 or 10.1.0.4).
TIA,
Holger
10.1.0.4 patch fixed above problem
Holger Schweichler, October 18, 2005 - 5:16 am UTC
... just wanted to let you know upgrading to 10.1.0.4 indeed fixed the problem, so it really looks like there's a bug in 10.1.0.3.
Holger ;-)
October 18, 2005 - 9:10 am UTC
Thank you very much for the followup!
Trying to use a shell script
Deba, November 10, 2005 - 12:50 pm UTC
Hi Tom,
I am trying to run a shell script using specified code.
Under SYS user :
=================
SQL> begin
2 dbms_java.grant_permission
3 ('YMDBAADM',
4 'java.io.FilePermission',
' 5 /nas/orasoft/baracuda/oracle/scripts/x.sh',
6 'execute');
7
8 dbms_java.grant_permission
( 9 'YMDBAADM',
10 'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
end;
/ 11 12 13 14
PL/SQL procedure successfully completed.
Under Oracle OS user
====================
/nas/orasoft/baracuda/oracle/scripts> ls -l x.sh
-rwxrwxrwx 1 oracle oinstall 66 Nov 10 17:11 x.sh
/nas/orasoft/baracuda/oracle/scripts> pg x.sh
echo executing
ls > /nas/orasoft/baracuda/oracle/scripts/java.txt
Under YMDBAADM :
================
SQL> edit
Wrote file afiedt.buf
1 create or replace and compile java source named "DebaShellUtil"
2 as
3 import java.io.*;
4 import java.lang.*;
5 public class DebaShellUtil extends Object
6 {
7 public static int RunThis(String args)
8 {
9 Runtime rt = Runtime.getRuntime();
10 int rc = -1;
11 try
12 {
13 Process p = rt.exec(args);
14 int bufSize = 4096;
15 BufferedInputStream bis =
16 new BufferedInputStream(p.getInputStream(), bufSize);
17 int len;
18 byte buffer[] = new byte[bufSize];
19 // Echo back what the program spit out
20 while ((len = bis.read(buffer, 0, bufSize)) != -1)
21 System.out.write(buffer, 0, len);
22 rc = p.waitFor();
23 }
24 catch (Exception e)
25 {
26 e.printStackTrace();
27 rc = -1;
28 }
29 finally
30 {
31 return rc;
32 }
33 }
34* }
35 /
Java created.
SQL> edit
Wrote file afiedt.buf
1 create or replace function RUN_CMD(p_cmd in varchar2) return number
2 as
3 language java
4* name 'DebaShellUtil.RunThis(java.lang.String) return integer';
SQL> /
Function created.
SQL> variable x number;
SQL> set serveroutput on;
SQL> exec dbms_java.set_output(100000);
PL/SQL procedure successfully completed.
SQL> exec :x := RUN_CMD('/nas/orasoft/baracuda/oracle/scripts/x.sh');
PL/SQL procedure successfully completed.
SQL> exec dbms_java.set_output(100000);
PL/SQL procedure successfully completed.
SQL> exec :x := RUN_CMD('/nas/orasoft/baracuda/oracle/scripts/x.sh');
PL/SQL procedure successfully completed.
You can see that there is no output. There is permission for the script on OS level. If I use follwoing
exec :x := RUN_CMD('/usr/bin/sh /nas/orasoft/baracuda/oracle/scripts/x.sh');
Then it is running fine. But you have already said this is not good idea to use, so I would like to know where is the problem in above mentioned process ??
Thanks
Deba
November 11, 2005 - 11:55 am UTC
you are missing an important line in the shell script
#!/bin/sh
on line one and remember, the environment might not be what you think in the shell script when run from the database (different environment) so best to fully qualify things (prevent trojan horses - find the right programs)
Trying to execute shell script
A reader, November 15, 2005 - 12:32 pm UTC
Hi Tom,
In OS I have created two files as follows :
/nas/orasoft/baracuda/oracle/scripts> pg x.sh
#!/bin/sh
echo executing
sleep 60
ls > /nas/orasoft/baracuda/oracle/scripts/java.txt
echo ending x.sh
/nas/orasoft/baracuda/oracle/scripts> pg y.sh
#!/bin/sh
echo calling x.sh
nohup /nas/orasoft/baracuda/oracle/scripts/x.sh &
echo calling y.sh
chomd 777 x.sh
chmod 777 y.sh
Under SYS account I have executed following code :
begin
dbms_java.grant_permission
('YMDBAADM',
'java.io.FilePermission',
'/usr/bin/sh',
'execute');
dbms_java.grant_permission
('YMDBAADM',
'java.io.FilePermission',
'/nas/orasoft/baracuda/oracle/scripts/y.sh',
'execute');
dbms_java.grant_permission
('YMDBAADM',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
end;
/
Connecting to the database thru STPS2 :
connect YMDBAADM/YMDBAADM
Connected.
create or replace and compile java source named "DebaShellUtil"
as
import java.io.*;
import java.lang.*;
public class DebaShellUtil extends Object
{
public static int RunThis(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;
}
}
}
/
create or replace function RUN_CMD(p_cmd in varchar2) return number
as
language java
name 'DebaShellUtil.RunThis(java.lang.String) return integer';
/
variable x number;
set serveroutput on
exec dbms_java.set_output(100000);
SQL> exec :x := RUN_CMD('/nas/orasoft/baracuda/oracle/scripts/y.sh');
calling x.sh
calling y.sh
executing
ending x.sh
PL/SQL procedure successfully completed.
Thanks for your any help.
Deba
November 15, 2005 - 1:56 pm UTC
dbms_java.grant_permission
('YMDBAADM',
'java.io.FilePermission',
'/usr/bin/sh',
'execute');
that's not good - that means "run anything"
sort of wished you had included "the problem" though....
but if it is because "it is waiting till x is done", that is something you'll need to poke around with in the java code, likely the waitfor call.
Trying to execute shell script
A reader, November 15, 2005 - 12:35 pm UTC
Hi Tom,
In the above post you can see that there is no effect of "&" . But I want to execute a sehll in the background . Now how we can get this ???
Deba
execute in background
EBer, December 15, 2005 - 10:16 am UTC
You can exec that command from a batch file and inside you write: command.sh &
If you want that command to be independent and hangup immune,
you can use command "nohup", but you can't have the output back.
Hope this hepls.
EBer
Is it possible without Java ?
EBer, December 15, 2005 - 10:29 am UTC
We haven't JServer in Production DB.
December 15, 2005 - 10:58 am UTC
you can use C based external routines as well.
in 10g, the scheduler can run external jobs natively.
You might want stderr as well as stdout
Scott Swank, December 29, 2005 - 5:00 pm UTC
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "host"
AS
import java.io.*;
public class host
{
public static int runCommand(String command, String[] output)
{
StringBuffer outputBuffer = new StringBuffer();
output[0] = "";
Runtime rt = Runtime.getRuntime();
int rc = -1;
try
{
Process p = rt.exec(command);
String line = new String();
BufferedReader br;
br = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = br.readLine()) != null)
outputBuffer.append(line);
br.close();
br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while ((line = br.readLine()) != null)
outputBuffer.append(line);
br.close();
if (outputBuffer.length() > 32000)
{
output[0] = new String(outputBuffer.substring(0,32000));
}
else
{
output[0] = new String(outputBuffer);
}
rc = p.waitFor();
//rc = p.exitValue();
}
catch (Exception e)
{
output[0] = e.toString();
rc = -1;
}
finally
{
return rc;
}
}
}
/
Is there any way to wrap java source
Ian, January 18, 2006 - 10:46 am UTC
Is there any way to wrap java source in the same way that you can wrap pl/sql packages?
Regards
Ian
January 19, 2006 - 7:49 am UTC
you can load bytecode instead of java source.
Su Baba, March 05, 2006 - 2:00 pm UTC
Would Java procedures cache cursors so no soft parses are required much like PL/SQL does?
March 06, 2006 - 8:32 am UTC
No, not unless you explicity make it happen in your own code.
A reader, March 06, 2006 - 12:46 pm UTC
When you say "not unless you explicity make it happen in your own code", do you mean opening a cursor in your Java code and keep using it until you don't need it any more?
March 08, 2006 - 4:10 pm UTC
or using jdbc statement caching or something - but "something" has to be explicitly enabled, jdbc does not do it by itself.
Yogesh Shejwal, March 31, 2006 - 6:14 am UTC
I want to Pass TableName and Column_name,But the Column_name Datatype is CLOB.FRONT End is Forms9iDS.
In Backend i have Created A funtion that accepts all the above.The Function i tested in Back end works fine.But at front end i just get a Blank screen.
(Note: I could not Find the Page to Submit the Question so i am writing my Question here. I am a regular User Of these Site..gets lot of information)
March 31, 2006 - 12:22 pm UTC
(note: the front page of this website sort of has the box that says:
Sorry I have a large backlog right now, please ask a question later
See the "other resources" tab above and to the left for recommendations of places to go to get answers to questions!
when I'm not taking questions)
I've no idea why you would get a "blank screen", I don't really know what you are really even doing.
cannot get this batch to run
oracledb, May 01, 2006 - 3:20 pm UTC
Tim,
i keeping getting null on windows 2000,but execute fine on windows 2003..
windows 2000
SQL> SET SERVEROUTPUT ON SIZE 1000000
SQL> CALL DBMS_JAVA.SET_OUTPUT(1000000);
Call completed.
SQL> BEGIN
2 PAS_HOST_COMMAND (p_command => '\\point-code\code$\sql\dev\sqltam\misc\test.bat');
3 EXCEPTION
4 WHEN OTHERS
5 THEN
6 DBMS_OUTPUT.PUT_LINE (SQLCODE);
7 DBMS_OUTPUT.PUT_LINE (SQLERRM);
8 END;
9 /
null
PL/SQL procedure successfully completed.
code for test.bat ==> move test1.txt test2.txt
------------------------------------------
windows 2003
SQL> BEGIN
2 PAS_HOST_COMMAND (p_command => '\\point-code\code$\sql\dev\sqltam\misc\test.bat');
3 EXCEPTION
4 WHEN OTHERS
5 THEN
6 DBMS_OUTPUT.PUT_LINE (SQLCODE);
7 DBMS_OUTPUT.PUT_LINE (SQLERRM);
8 END;
9 /
Process out :
Process out :C:\oracle\ora81\DATABASE>SQLPLUS.EXE BT15/BT15@BT15
@\\point-code\code$\sql\dev\sqltam\misc\TEST.SQL
PL/SQL procedure successfully completed.
code for test.bat ==> move test1.txt test2.txt
May 02, 2006 - 3:24 am UTC
what sort of debugging have you tried on your own?
I mean - if you have two machines here (forget the OS version for a minute) who is to say they are remotely configured the "same". that UNC name (that can be very tricky to use with services, if it can be used at all), does it really exist for the user that the database service is running as.
you don't even mention database versions :(
cannot get this batch to run
oracledb, May 02, 2006 - 6:24 pm UTC
not sure if my post work so..
both are on oracle 8.1.7.4.1,
i don't know what the null means? and i don't really know how to debug..i've tried it on the 2000 using local path and network path..
May 03, 2006 - 1:45 am UTC
... and i don't really know how to debug ...
uh oh. start by putting some DEBUG CODE into your java subroutine, to sort of try to figure out where it is going awry.
System.out.println()'s
Error Bound
Tom, July 03, 2006 - 8:56 am UTC
Hi Tom,
I have tried your example on a Sun Machine and I have got the next:
14:53:41 SQL> exec rc('/usr/bin/ps -ef');
java.lang.ArrayIndexOutOfBoundsException
at Util.RunThis(Util.java:14)
Procedimiento PL/SQL terminado correctamente.
14:53:49 SQL> exec rc('/usr/bin/id > f');
java.lang.ArrayIndexOutOfBoundsException
at Util.RunThis(Util.java:14)
What could be the cause of this?
I'll appreciate very much your help.
July 07, 2006 - 3:30 pm UTC
did you ctl-f for ArrayIndexOutOfBoundsException
on this very page?
I have just solved my problem
Jorge, July 03, 2006 - 11:09 am UTC
Thanks for your help!. I found the solution above.
Solution to tricky "env" problem
Jay Bostock, July 20, 2006 - 5:31 am UTC
Okay - this thread is getting way out of hand, but I just wanted to contribute a quick solution that I've used to make running a script as a different user from oracle, where you have all the environment issues (I'm sure it's in AskTom somewhere!). I've done it using rsh (ssh would be better). the command executed from within oracle would be something like:
sql> exec rc('/usr/bin/rsh localhost -l <username> <myShellScript>');
It doesn't have to be localhost, you can use any host name. You have to create $HOME/.rhosts file in the account you want to connect to with the line 'localhost oracle' (again, if the two accounts are on different machines, use the hostname rather than localhost. This allows oracle to login without supplying the password. A remote shell is created as the user you are connecting with (with the correct env), the command is run (in my case myShellScript, but any command can be run) and then the remote shell is exited.
It works brilliantly for me and saves loads of bother/confusion!
Hope this helps someone.
Cheers
Jay
Stored Proc Execution in Unix
A reader, August 09, 2006 - 8:33 am UTC
Hi ,
Can you let me know the commands to be used to execute a oracle Stored Proc in C Shell script and to output the results of the execution as to whether the execution was successful or there was an Exception in the execution to a Text file
Thanks for the same.
August 09, 2006 - 10:55 am UTC
same why you would execute anything and log the output in C shell.
anyway, create a script, eg
$ cat test.sql
exec dbms_output.put_line('hello world');
exit
so, the procedure I want to run is dbms_output. You run it as follows:
$ sqlplus / @test
SQL*Plus: Release 10.2.0.1.0 - Production on Wed Aug 9 10:40:17 2006
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
hello world
PL/SQL procedure successfully completed.
Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
Then, you just use redirection to capture the output. pipe to grep if you just one "success":
$ sqlplus / @test | grep 'successfully'
PL/SQL procedure successfully completed.
or better yet, egrep to get success or failure (I'll make it fail)
$ sqlplus / @test | egrep '(successfully|ORA-)'
PL/SQL procedure successfully completed.
$ cat test.sql
exec dbms_output.put_line('hello world'); raise PROGRAM_ERROR;
exit
$ sqlplus / @test | egrep '(successfully|ORA-)'
ORA-06501: PL/SQL: program error
ORA-06512: at line 1
Did something in Java change between 9i and 10g?
Ron, August 09, 2006 - 2:04 pm UTC
Tom,
I have a java stored procedure that worked like a charm in 9i but when I try to use it on a 10g database, it doesn't seem to work. I use it to capture the UNIX TZ environment variable of the database and place it in a PL/SQL variable. Watch how it works in 9i and then doesn't in 10g:
12:37:34 SQL> connect sys@resd as sysdba
Enter password: *******
Connected.
12:37:35 SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.7.0 - 64bit Production
PL/SQL Release 9.2.0.7.0 - Production
CORE 9.2.0.7.0 Production
TNS for Solaris: Version 9.2.0.7.0 - Production
NLSRTL Version 9.2.0.7.0 - Production
Elapsed: 00:00:00.00
12:37:45 SQL> begin
12:38:06 2 dbms_java.grant_permission
12:38:06 3 ( 'MECSPY', 'SYS:java.io.FilePermission',
12:38:06 4 '/opt/app/oracle/admin/cadhd/create/test_tz.sh',
12:38:06 5 'execute' );
12:38:06 6
12:38:06 7 dbms_java.grant_permission
12:38:06 8 ('SYS',
12:38:06 9 'java.lang.RuntimePermission',
12:38:06 10 '*',
12:38:06 11 'writeFileDescriptor' );
12:38:06 12 end;
12:38:06 13 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:02.08
12:38:11 SQL> connect mecspy@resd
Enter password: *******
Connected.
12:38:29 SQL> create or replace
12:38:52 2 FUNCTION run_command_java_fx (
12:38:52 3 fv_command IN VARCHAR2,
12:38:52 4 fv_output OUT VARCHAR2
12:38:52 5 )
12:38:52 6 RETURN NUMBER
12:38:52 7 AS
12:38:52 8 LANGUAGE JAVA
12:38:52 9 NAME 'NcgOSj.runOsCmd( java.lang.String,
12:38:52 10 java.lang.String[] ) return integer';
12:38:52 11 /
Function created.
Elapsed: 00:00:00.02
12:38:53 SQL>
12:38:53 SQL> create or replace
12:38:53 2 PROCEDURE run_command_java (
12:38:53 3 fv_command IN VARCHAR2,
12:38:53 4 fv_output OUT VARCHAR2
12:38:53 5 )
12:38:53 6 IS
12:38:53 7 ln_return_code NUMBER;
12:38:53 8 BEGIN
12:38:53 9 ln_return_code := run_command_java_fx (fv_command, fv_output);
12:38:53 10 END run_command_java;
12:38:53 11 /
Procedure created.
Elapsed: 00:00:00.00
12:38:53 SQL>
12:38:53 SQL> CREATE OR REPLACE AND COMPILE
12:38:53 2 JAVA SOURCE NAMED "NcgOSj"
12:38:53 3 AS
12:38:53 4 import java.io.*;
12:38:53 5 import java.lang.*;
12:38:53 6
12:38:53 7 public class NcgOSj extends Object
12:38:53 8 {
12:38:53 9 public static int runOsCmd(String OsCmdLine,
12:38:53 10 String[] CmdOutput)
12:38:53 11 {
12:38:53 12 Runtime rt = Runtime.getRuntime();
12:38:53 13 int rc = -1;
12:38:53 14 String coutput = " ";
12:38:53 15 String ot = " " ;
12:38:53 16
12:38:53 17 if (OsCmdLine.length() < 1) {
12:38:53 18 System.out.println("USAGE: java NcgOSj.runOsCmd \'cmd\' OutputStringVariable"
);
12:38:53 19 System.exit(1);
12:38:53 20 }
12:38:53 21 try
12:38:53 22 {
12:38:53 23 // The exec() method in java.lang.Runtime is overloaded and
12:38:53 24 // can be called in different forms. The following use illustrates
12:38:53 25 // the simplest form of exec() which takes a string as a parameter.
12:38:53 26 //
12:38:53 27 // Execute the command using the Runtime object variable 'rt' and
12:38:53 28 // get the process 'p' which controls this command
12:38:53 29 Process p = rt.exec(OsCmdLine);
12:38:53 30
12:38:53 31 int bufSize = 4096;
12:38:53 32 BufferedInputStream bis =
12:38:53 33 new BufferedInputStream(p.getInputStream(), bufSize);
12:38:53 34 int len;
12:38:53 35 byte buffer[] = new byte[bufSize];
12:38:53 36
12:38:53 37 // Echo back what the program spit out
12:38:53 38 while ((len = bis.read(buffer, 0, bufSize)) != -1) {
12:38:53 39 System.out.write(buffer, 0, len);
12:38:53 40 ot = new String(buffer, 0, len) ;
12:38:53 41 coutput = coutput + ot ;
12:38:53 42 }
12:38:53 43 // Wait for the process 'p' to finish and get the return code
12:38:53 44 // from the process
12:38:53 45 rc = p.waitFor();
12:38:53 46 }
12:38:53 47 catch (Exception e)
12:38:53 48 {
12:38:53 49 e.printStackTrace();
12:38:53 50 rc = -1;
12:38:53 51 }
12:38:53 52 finally
12:38:53 53 {
12:38:53 54 CmdOutput[0] = coutput;
12:38:53 55 return rc;
12:38:53 56 }
12:38:53 57 }
12:38:53 58 }
12:38:53 59 /
Java created.
Elapsed: 00:00:04.06
12:38:59 SQL> connect mecspy@resd
Enter password: *******
Connected.
12:39:06 SQL> variable outpt varchar2(2000)
12:39:31 SQL> set serveroutput on
12:39:31 SQL> exec dbms_java.set_output(100000);
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.05
12:39:33 SQL> exec run_command_java('/opt/app/oracle/admin/cadhd/create/test_tz.sh', :outpt);
US/Central
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.02
12:40:34 SQL> print :outpt
OUTPT
----------------------------------------------------------------------------------------------------
US/Central
So that worked great - the :outpt variable contains the UNIX TZ setting. Now I go over to a 10g database running on the same server and run the exact same processes including the exact same shell script:
12:43:28 SQL> connect sys@cadhd as sysdba
Enter password: ***********
Connected.
12:43:29 SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.2.0 - 64bi
PL/SQL Release 10.2.0.2.0 - Production
CORE 10.2.0.2.0 Production
TNS for Solaris: Version 10.2.0.2.0 - Production
NLSRTL Version 10.2.0.2.0 - Production
Elapsed: 00:00:00.00
12:43:40 SQL> begin
12:43:53 2 dbms_java.grant_permission
12:43:53 3 ( 'MECSPY', 'SYS:java.io.FilePermission',
12:43:53 4 '/opt/app/oracle/admin/cadhd/create/test_tz.sh',
12:43:53 5 'execute' );
12:43:53 6
12:43:53 7 dbms_java.grant_permission
12:43:53 8 ('SYS',
12:43:53 9 'java.lang.RuntimePermission',
12:43:53 10 '*',
12:43:53 11 'writeFileDescriptor' );
12:43:53 12 end;
12:43:53 13 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.00
12:43:54 SQL> connect mecspy@cadhd
Enter password: *******
Connected.
12:44:02 SQL> create or replace
12:44:12 2 FUNCTION run_command_java_fx (
12:44:12 3 fv_command IN VARCHAR2,
12:44:12 4 fv_output OUT VARCHAR2
12:44:12 5 )
12:44:12 6 RETURN NUMBER
12:44:12 7 AS
12:44:12 8 LANGUAGE JAVA
12:44:12 9 NAME 'NcgOSj.runOsCmd( java.lang.String,
12:44:12 10 java.lang.String[] ) return integer';
12:44:12 11 /
Function created.
Elapsed: 00:00:00.00
12:44:12 SQL>
12:44:12 SQL> create or replace
12:44:12 2 PROCEDURE run_command_java (
12:44:12 3 fv_command IN VARCHAR2,
12:44:12 4 fv_output OUT VARCHAR2
12:44:12 5 )
12:44:12 6 IS
12:44:12 7 ln_return_code NUMBER;
12:44:12 8 BEGIN
12:44:12 9 ln_return_code := run_command_java_fx (fv_command, fv_output);
12:44:12 10 END run_command_java;
12:44:12 11 /
Procedure created.
Elapsed: 00:00:00.00
12:44:12 SQL>
12:44:12 SQL> CREATE OR REPLACE AND COMPILE
12:44:12 2 JAVA SOURCE NAMED "NcgOSj"
12:44:12 3 AS
12:44:12 4 import java.io.*;
12:44:12 5 import java.lang.*;
12:44:12 6
12:44:12 7 public class NcgOSj extends Object
12:44:12 8 {
12:44:12 9 public static int runOsCmd(String OsCmdLine,
12:44:12 10 String[] CmdOutput)
12:44:12 11 {
12:44:12 12 Runtime rt = Runtime.getRuntime();
12:44:12 13 int rc = -1;
12:44:12 14 String coutput = " ";
12:44:12 15 String ot = " " ;
12:44:12 16
12:44:12 17 if (OsCmdLine.length() < 1) {
12:44:13 18 System.out.println("USAGE: java NcgOSj.runOsCmd \'cmd\' OutputStringVariable"
);
12:44:13 19 System.exit(1);
12:44:13 20 }
12:44:13 21 try
12:44:13 22 {
12:44:13 23 // The exec() method in java.lang.Runtime is overloaded and
12:44:13 24 // can be called in different forms. The following use illustrates
12:44:13 25 // the simplest form of exec() which takes a string as a parameter.
12:44:13 26 //
12:44:13 27 // Execute the command using the Runtime object variable 'rt' and
12:44:13 28 // get the process 'p' which controls this command
12:44:13 29 Process p = rt.exec(OsCmdLine);
12:44:13 30
12:44:13 31 int bufSize = 4096;
12:44:13 32 BufferedInputStream bis =
12:44:13 33 new BufferedInputStream(p.getInputStream(), bufSize);
12:44:13 34 int len;
12:44:13 35 byte buffer[] = new byte[bufSize];
12:44:13 36
12:44:13 37 // Echo back what the program spit out
12:44:13 38 while ((len = bis.read(buffer, 0, bufSize)) != -1) {
12:44:13 39 System.out.write(buffer, 0, len);
12:44:13 40 ot = new String(buffer, 0, len) ;
12:44:13 41 coutput = coutput + ot ;
12:44:13 42 }
12:44:13 43 // Wait for the process 'p' to finish and get the return code
12:44:13 44 // from the process
12:44:13 45 rc = p.waitFor();
12:44:13 46 }
12:44:13 47 catch (Exception e)
12:44:13 48 {
12:44:13 49 e.printStackTrace();
12:44:13 50 rc = -1;
12:44:13 51 }
12:44:13 52 finally
12:44:13 53 {
12:44:13 54 CmdOutput[0] = coutput;
12:44:13 55 return rc;
12:44:13 56 }
12:44:13 57 }
12:44:13 58 }
12:44:13 59 /
Java created.
Elapsed: 00:00:01.04
12:44:15 SQL> connect mecspy@cadhd
Enter password: *******
Connected.
12:44:35 SQL> variable outpt varchar2(2000)
12:44:36 SQL> set serveroutput on
12:44:36 SQL> exec dbms_java.set_output(100000);
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.03
12:44:37 SQL> exec run_command_java('/opt/app/oracle/admin/cadhd/create/test_tz.sh', :outpt);
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.02
12:44:57 SQL> print :outpt
OUTPT
----------------------------------------------------------------------------------------------------
Note how this time in the 10g database the :outpt variable is empty - no UNIX TZ variable setting. Did something subtle in
Java happen to cause this in 10g?
August 09, 2006 - 4:53 pm UTC
everything but the sh script :(
oh well.
anyway, are you SURE the TZ environment variable is in fact set? Why not quickly test some other variable - like ORACLE_HOME, pretty sure that one would be.
(just because they are on the same machine doesn't mean they have the same environment)
Here's the .sh script and the test using it
Ron, August 10, 2006 - 8:59 am UTC
Here's the contents of the test_tz.sh script that shows the value of the ORACLE_HOME followed by the java test too:
---- in unix
dm556:/opt/app/oracle/admin/cadhd/create:oracle >cat test_tz.sh
#!/bin/ksh
export VALUE=`env | grep ORACLE_HOME | awk -F= '{print $2}'`
echo $VALUE
dm556:/opt/app/oracle/admin/cadhd/create:oracle >test_tz.sh
/opt/app/oracle/product/10.2.0.2.0
----- back to sql*plus
07:35:34 SQL> connect sys@cadhd as sysdba
Enter password: ***********
Connected.
07:44:26 SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.2.0 - 64bi
PL/SQL Release 10.2.0.2.0 - Production
CORE 10.2.0.2.0 Production
TNS for Solaris: Version 10.2.0.2.0 - Production
NLSRTL Version 10.2.0.2.0 - Production
Elapsed: 00:00:00.00
07:44:34 SQL> begin
07:45:19 2 dbms_java.grant_permission
07:45:19 3 ( 'MECSPY', 'SYS:java.io.FilePermission',
07:45:19 4 '/opt/app/oracle/admin/cadhd/create/test_tz.sh',
07:45:19 5 'execute' );
07:45:19 6
07:45:19 7 dbms_java.grant_permission
07:45:19 8 ('SYS',
07:45:19 9 'java.lang.RuntimePermission',
07:45:19 10 '*',
07:45:19 11 'writeFileDescriptor' );
07:45:19 12 end;
07:45:19 13 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.04
07:45:19 SQL> connect mecspy@cadhd
Enter password: *******
Connected.
07:46:57 SQL> create or replace
07:47:14 2 FUNCTION run_command_java_fx (
07:47:14 3 fv_command IN VARCHAR2,
07:47:14 4 fv_output OUT VARCHAR2
07:47:14 5 )
07:47:14 6 RETURN NUMBER
07:47:14 7 AS
07:47:14 8 LANGUAGE JAVA
07:47:14 9 NAME 'NcgOSj.runOsCmd( java.lang.String,
07:47:14 10 java.lang.String[] ) return integer';
07:47:14 11 /
Function created.
Elapsed: 00:00:00.00
07:47:14 SQL>
07:47:14 SQL> create or replace
07:47:14 2 PROCEDURE run_command_java (
07:47:14 3 fv_command IN VARCHAR2,
07:47:14 4 fv_output OUT VARCHAR2
07:47:14 5 )
07:47:14 6 IS
07:47:14 7 ln_return_code NUMBER;
07:47:14 8 BEGIN
07:47:14 9 ln_return_code := run_command_java_fx (fv_command, fv_output);
07:47:14 10 END run_command_java;
07:47:14 11 /
Procedure created.
Elapsed: 00:00:00.00
07:47:14 SQL>
07:47:14 SQL> CREATE OR REPLACE AND COMPILE
07:47:14 2 JAVA SOURCE NAMED "NcgOSj"
07:47:14 3 AS
07:47:14 4 import java.io.*;
07:47:14 5 import java.lang.*;
07:47:14 6
07:47:14 7 public class NcgOSj extends Object
07:47:14 8 {
07:47:14 9 public static int runOsCmd(String OsCmdLine,
07:47:14 10 String[] CmdOutput)
07:47:14 11 {
07:47:14 12 Runtime rt = Runtime.getRuntime();
07:47:14 13 int rc = -1;
07:47:14 14 String coutput = " ";
07:47:14 15 String ot = " " ;
07:47:14 16
07:47:14 17 if (OsCmdLine.length() < 1) {
07:47:14 18 System.out.println("USAGE: java NcgOSj.runOsCmd \'cmd\' OutputStringVariable"
);
07:47:14 19 System.exit(1);
07:47:14 20 }
07:47:14 21 try
07:47:14 22 {
07:47:14 23 // The exec() method in java.lang.Runtime is overloaded and
07:47:14 24 // can be called in different forms. The following use illustrates
07:47:14 25 // the simplest form of exec() which takes a string as a parameter.
07:47:14 26 //
07:47:14 27 // Execute the command using the Runtime object variable 'rt' and
07:47:14 28 // get the process 'p' which controls this command
07:47:14 29 Process p = rt.exec(OsCmdLine);
07:47:14 30
07:47:14 31 int bufSize = 4096;
07:47:14 32 BufferedInputStream bis =
07:47:14 33 new BufferedInputStream(p.getInputStream(), bufSize);
07:47:14 34 int len;
07:47:14 35 byte buffer[] = new byte[bufSize];
07:47:14 36
07:47:14 37 // Echo back what the program spit out
07:47:14 38 while ((len = bis.read(buffer, 0, bufSize)) != -1) {
07:47:14 39 System.out.write(buffer, 0, len);
07:47:14 40 ot = new String(buffer, 0, len) ;
07:47:14 41 coutput = coutput + ot ;
07:47:14 42 }
07:47:14 43 // Wait for the process 'p' to finish and get the return code
07:47:14 44 // from the process
07:47:14 45 rc = p.waitFor();
07:47:14 46 }
07:47:14 47 catch (Exception e)
07:47:14 48 {
07:47:14 49 e.printStackTrace();
07:47:14 50 rc = -1;
07:47:14 51 }
07:47:14 52 finally
07:47:14 53 {
07:47:14 54 CmdOutput[0] = coutput;
07:47:14 55 return rc;
07:47:14 56 }
07:47:14 57 }
07:47:14 58 }
07:47:14 59 /
Java created.
Elapsed: 00:00:01.01
07:47:16 SQL> connect mecspy@cadhd
Enter password: *******
Connected.
07:47:26 SQL> variable outpt varchar2(2000)
07:47:51 SQL> set serveroutput on
07:47:51 SQL> exec dbms_java.set_output(100000);
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.01
07:48:17 SQL> exec run_command_java('/opt/app/oracle/admin/cadhd/create/test_tz.sh', :outpt);
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.01
07:52:07 SQL> print :outpt
OUTPT
----------------------------------------------------------------------------------------------------
August 10, 2006 - 9:38 am UTC
can you tell if the script is being executed at all? touch a file or something (eg: debug it, add trace/diagnostic information)
The script's not being executed.
Ron, August 10, 2006 - 10:25 am UTC
That's a good idea. I touched a file within the .sh script. When I run it from the 9i database I can see the touched file on the file system - when I run it in the 10g database the touched file isn't there proving that the script isn't being executed. Now I just have to figure out why.
Cannot compile ...
Stefanie, August 23, 2006 - 9:32 am UTC
Trying to compile the Java code I get errors:
create or replace and compile
java source named "Util"
as
import java.io.*;
import java.lang.*;
public class Util extends Object
{
public static int RunThis(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;
}
}
* }
/
Oracle tells me the following:
Util:7: Class string not found.
Util:9: Class runtime not found.
Util:9: Undefined variable or class name: runtime
Util:14: Class process not found.
And so on.
There are public synonyms and execution grants on all Java stuff under sys. My user has every Java-ish role assigned.
Where does this error come from?
Thanks for your help,
Steff
August 27, 2006 - 3:40 pm UTC
can we see a cut and paste?
ops$tkyte%ORA10GR2> create or replace and compile
2 java source named "Util"
3 as
4 import java.io.*;
5 import java.lang.*;
6 public class Util extends Object
7 {
8 public static int RunThis(String args)
9 {
10 Runtime rt = Runtime.getRuntime();
11 int rc = -1;
12 try
13 {
14 Process p = rt.exec(args);
15 int bufSize = 4096;
16 BufferedInputStream bis =
17 new BufferedInputStream(p.getInputStream(), bufSize);
18 int len;
19 byte buffer[] = new byte[bufSize];
20 // Echo back what the program spit out
21 while ((len = bis.read(buffer, 0, bufSize)) != -1)
22 System.out.write(buffer, 0, len);
23 rc = p.waitFor();
24 }
25 catch (Exception e)
26 {
27 e.printStackTrace();
28 rc = -1;
29 }
30 finally
31 {
32 return rc;
33 }
34 }
35 }
36 /
Java created.
Scheiss Gallier
Stefanie, August 23, 2006 - 10:22 am UTC
It was the asterix in the second last line ... *aaargh* ... ;o)
unable to print out put of oerr command in pl/sql
V Bhavani Sankar, August 28, 2006 - 3:43 am UTC
Dear Tom,
Thank you very much for u r example . with that example i was able to run almost all os commans. but i'm unable to print the output of "oerr " tool.
Does any other settings are required for running tools like oerr.
here is sample output
LAB65>select test1_call_cmd('/bin/ls -la') from dual;
TEST1_CALL_CMD('/BIN/LS-LA')
---------------------------------------------------------------------------------
total 28320
drwxr-xr-x 2 oracle dba 4096 Aug 14 10:24 .
drwxr-xr-x 55 oracle dba 4096 Apr 20 17:10 ..
-rwxr-xr-x 1 oracle dba 1544 Apr 15 16:16 hc_aplab65.dat
-rwxr-xr-x 1 oracle dba 1544 Apr 13 17:05 hc_ora10g.dat
-rwxr-xr-x 1 oracle dba 1400 Jul 15 13:18 initaplab65.ora
-rwxr-xr-x 1 oracle dba 12920 May 3 2001 initdw.ora
-rwxr-xr-x 1 oracle dba 8385 Sep 11 1998 init.ora
-rwxr-xr-x 1 oracle dba 24 Apr 15 16:16 lkAPLAB65
-rw-r----- 1 oracle dba 1536 Aug 24 14:28 orapwaplab65
-rw-r----- 1 oracle dba 1536 Aug 3 16:41 orapwaplab65.bak
-rw-r----- 1 oracle dba 1536 Aug 3 17:01 orapwaplab65.bak1
-rw-r----- 1 oracle dba 1536 Aug 4 10:11 orapwaplab65.bak2
-rw-r----- 1 oracle dba 28819456 Aug 25 14:40 snapcf_aplab65.f
-rwxr-xr-x 1 oracle dba 3584 Apr 20 22:06 spfileaplab65.bak
-rw-r----- 1 oracle dba 3584 Aug 28 12:01 spfileaplab65.ora
-rwxr-xr-x 1 root root 2622 Apr 19 15:33 sqlnet.log
LAB65>select test1_call_cmd('/apps/app/oracle/product/10.2.0/bin/oerr ora 1003') from dual;
TEST1_CALL_CMD('/APPS/APP/ORAC
-----------------------------------------------------------------------------------------------
Thank you very much for the help
August 28, 2006 - 10:36 am UTC
u r ???
/bin/ls - that is an executable
/.../oerr - that is a shell script
ctl-f for cnelson and try some of that.
Thank you for the responce.
Bhavani Sankar, August 29, 2006 - 3:09 am UTC
Dear Tom,
sorry for that "u r" in last reply.
i dont think my problem with enironment. because simple echo command from a script also not giving output.
when i run any script for pl/sql function the wait status of Process p.waitfor() coming as 255.
here is what i've done.
exec dbms_java.grant_permission('DOTSOFT','SYS:java.io.FilePermission','/home/oracle/sayhi','execute');
contents of sayhi file
[oracle@lab65 ~]$ cat sayhi
echo hello
permission of the file
[oracle@lab65 ~]$ ll sayhi
-rwxrwxrwx 1 oracle dba 24 Aug 29 12:19 sayhi
select test_call_cmd('/home/oracle/showerr') from dual;
TEST_CALL_CMD('/HOME/ORACLE/SH
------------------------------
255
later i changed sayhi to
[oracle@lab65 ~]$ cat sayhi
/usr/bin/env
echo hello
once again i run the function
SQL> select test_call_cmd('/home/oracle/sayhi') from dual;
TEST_CALL_CMD('/HOME/ORACLE/SA
------------------------------
255
output is same.
if i directly call 'echo' then it is ok
select test_call_cmd('/bin/echo hello') from dual;
TEST_CALL_CMD('/BIN/ECHOHELLO
-----------------------------
0
SQL> exec test_call_fun('/bin/echo hello');
hello
PL/SQL procedure successfully completed.
SQL> exec test_call_fun('/home/oracle/sayhi');
PL/SQL procedure successfully completed.
i got oerr output with direct grep command. my problem is solved. but i want to know why scripts are not running even though they are by oracle itself.
Thank you very much for your help
August 29, 2006 - 7:12 am UTC
put a SHELL in the beginng of that script
#!/bin/sh
Thank you
A reader, August 30, 2006 - 3:28 am UTC
Thank you very much
One More time
Dick Goulet, October 18, 2006 - 4:32 pm UTC
Tom,
I found this very useful & thank you for it, but as a few above me have said I'm no JAVA head. What I want is to issue a 'df -k' on a file system(solaris) and get back the available disk space. What I get today is:
/dev/md/dsk/d2 12397228 3936915 8336341 33% /
What I want is: 8336341
Anyway to get there from here?
October 18, 2006 - 4:48 pm UTC
get that string from java....
and then substr it in sql/plsql :)
that is what *I* would do...
Host Command In Java
Dick Goulet, October 19, 2006 - 10:30 am UTC
Tom,
Can't we be a little more elegant?? I've done this with external C procedures before, but I'm trying to move into the 21st century. Thanks anyway, it was worth the effort to ask.
October 19, 2006 - 2:06 pm UTC
you may well be able to - but the problem is "i am not a java guru" either, I'm much better with plsql/sql and C :)
Running o/s commands from pl/sql
a reader, November 20, 2006 - 6:51 am UTC
I used the scripts from above to run the operating system command from within pl/sql. It doesn't return anything back to pl/sql program, it doesn't throw any error either. Below is the script that I have used. I know that granting privilege to /usr/bin/ksh is not a good idea, so if there is a workaround then please let me know.
Basically I am trying to get the available disk space on our file system. At the moment, my korn shell script contains hard coded file system but I ideally want to pass this as a parameter. However, I am not being able to run this even with the hardcoded file system, so need your help. Please let me know why it is not returning any result back to pl/sql program unit.
Thanks in advance
drop user rt_test cascade;
create user rt_test identified by rt_test;
grant connect, resource to rt_test;
begin
-- Grant execute permission on df to rt_test user.
dbms_java.grant_permission(
'rt_test', 'java.io.FilePermission',
'/usr/xpg4/bin/df',
'execute');
-- Grant execute permission on grep to rt_test user.
dbms_java.grant_permission(
'rt_test', 'java.io.FilePermission',
'/usr/xpg4/bin/grep',
'execute');
-- Grant execute permission on awk to rt_test user.
dbms_java.grant_permission(
'rt_test', 'java.io.FilePermission',
'/usr/xpg4/bin/awk',
'execute');
-- Grant execute permission on ksh to rt_test user.
dbms_java.grant_permission(
'rt_test', 'java.io.FilePermission',
'/usr/bin/ksh',
'execute');
-- Grant execute permission on dfp to rt_test user.
dbms_java.grant_permission(
'rt_test', 'java.io.FilePermission',
'/projects/atlas/dba/part/scripts/.temp/dfp',
'execute');
dbms_java.grant_permission
('rt_test',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
end;
/
-- The korn shell script /projects/atlas/dba/part/scripts/.temp/dfp contains
#!/usr/bin/ksh
df -k /export/data/db1|grep "^/" | awk '{print $4;}'
------------------------------------
connect rt_test/rt_test
create or replace and compile
java source named "Util"
as
import java.io.*;
import java.lang.*;
public class Util extends Object
{
public static int RunThis(String args, String[] cmdOutput)
{
Runtime rt = Runtime.getRuntime();
int rc = -1;
String coutput = " ";
String ot = " ";
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);
ot = new String(buffer, 0, len);
coutput = coutput + ot;
}
rc = p.waitFor();
}
catch (Exception e)
{
e.printStackTrace();
rc = -1;
}
finally
{
cmdOutput[0] = coutput;
return rc;
}
}
}
/
create or replace function RUN_CMD( p_cmd in varchar2, p_cmd_out out varchar2) return number as
language java
name 'Util.RunThis(java.lang.String, java.lang.String[]) return integer';
/
create or replace procedure RC(p_cmd in varchar2, p_cmd_out out varchar2) as
x number;
begin
x := run_cmd(p_cmd, p_cmd_out);
dbms_output.put_line('Cmd output:' || p_cmd_out);
end;
/
set serveroutput on size 1000000
execute dbms_java.set_output(1000000)
declare
r varchar2(4000);
begin
rc('/projects/atlas/dba/part/scripts/.temp/dfp', r);
dbms_output.put_line('Return value:' || r);
end;
/
running o/s commands using java
a reader, November 21, 2006 - 7:33 am UTC
Hi Tom,
Please could you reply to the above query. I am using 10.2.0.1 database.
Thanks
running o/s command using java
a reader, November 23, 2006 - 7:30 am UTC
Hi Tom,,
Please could you reply to the query above where I am trying to return the available disk space on a file system?
Thanks
Exception error
Krishna, November 27, 2006 - 1:57 am UTC
Hi Tom,
I am using Oracle9i Enterprise Edition Release 9.2.0.6.0 ver, I used the same code but while executing the procedure I am getting Exception errors
SQL> exec rc('/u13/mdrdev/ps');
java.lang.NoSuchMethodException: No applicable method found
at
oracle.aurora.util.JRIExtensions.getMaximallySpecificMethod(JRIExtensions.java)
at
oracle.aurora.util.JRIExtensions.getMaximallySpecificMethod(JRIExtensions.java)
BEGIN rc('/u03/radartst/ps'); END;
*
ERROR at line 1:
ORA-29531: no method RunThis in class util
ORA-06512: at "MDR.RUN_CMD", line 0
ORA-06512: at "MDR.RC", line 5
ORA-06512: at line 1
Thanks in Advance
November 27, 2006 - 7:58 am UTC
you did something, well, wrong.
look at the code again. You seem to be missing the "RunThis" method.
Exception error
user, November 27, 2006 - 2:31 am UTC
Hi Tom,
In continuation with the above problem, I am including all the code
create or replace procedure java_permission
as
begin
dbms_java.grant_permission
('MDR',
'java.io.FilePermission',
'/bin/ps',
'execute');
dbms_java.grant_permission
('MDR',
'java.io.FilePermission',
'/bin/sh',
'execute');dbms_java.grant_permission
('MDR',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
end;
--- executed sucessfully
create or replace and compile java source named util as
import java.io.*;
import java.lang.*;
public class Util extends Object
{
public static int RunThis(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;
}
}
}
-- compiled sucessfully
create or replace function RUN_CMD( p_cmd in varchar2) return number
as
language java
name 'Util.RunThis(java.lang.String[]) return integer';
-- compiled sucessfully
create or replace procedure RC(p_cmd in varchar2)
as
x number;
begin
x := run_cmd(p_cmd);
end;
-- compiled sucessfully
SQL> exec rc('/bin/ps');
java.lang.NoSuchMethodException: No applicable method found
at
oracle.aurora.util.JRIExtensions.getMaximallySpecificMethod(JRIExtensions.java)
at
oracle.aurora.util.JRIExtensions.getMaximallySpecificMethod(JRIExtensions.java)
BEGIN rc('/bin/ps'); END;
*
ERROR at line 1:
ORA-29531: no method RunThis in class util
ORA-06512: at "MDR.RUN_CMD", line 0
ORA-06512: at "MDR.RC", line 5
ORA-06512: at line 1
Thanks in Advance
November 27, 2006 - 8:42 am UTC
you need to put the "" around util again in the create or replace and lose the [] in the run_cmd function - ctl-f on this page for ArrayI and look at the code again, you are not using what I had last (for 9i)
running system commands using java
a reader, November 27, 2006 - 11:32 am UTC
could you reply to my query, the one before the last question (on returning the amount of disk space available in a file system using java).
thanks
November 27, 2006 - 7:34 pm UTC
back up and simplify it. what have you done to "debug" - have you had the script redirect to a file for example just to verify it "works", print out the environment, and so on.
Run time permission error
A reader, November 28, 2006 - 7:05 am UTC
Hi Tom,
Thanks for your code, this is very much helpful, I am getting errors when I want to run a sh file
I got the following permissions from DBA
dbms_java.grant_permission
('MDR',
'java.io.FilePermission',
'/bin/ps',
'execute');
dbms_java.grant_permission
('MDR',
'java.io.FilePermission',
'/bin/pwd',
'execute');
dbms_java.grant_permission
('MDR',
'java.io.FilePermission',
'/bin/sh',
'execute');
dbms_java.grant_permission
('MDR',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
I was able to run the following commands
exec rc('/bin/ps'); ---sucess with output
exec rc('/bin/pwd'); --output /opt/oracle/product9206/dbs
so every command is referring to this /opt/oracle/product9206/dbs directory
Actually I need to execute a sh file which is in /u13/mdrdev directory
I got the permission for this execution from dba as
execute dbms_java.grant_permission
('MDR','java.io.FilePermission','/bin/sh /u13/mdrdev/sample.sh', 'execute');
When I ran from linux this command is working
]$ /bin/sh /u13/mdrdev/sample.sh
but when I tried to execute the same as
exec rc('/bin/sh /u13/mdrdev/sample.sh'), I couldn't get any output
I feel the problem is in giving the permissions statement from DBA.
Your suggestions are very much needful,please help me in framing the DBA permission
Thanks in Advance
November 28, 2006 - 9:34 am UTC
do not use /bin/sh - you would give permission on /bin/sh and THAT WOULD LET YOU RUN VIRTUALLY ANYTHING.
grant execute on /u13/mdrdev/sample.sh
and make sure the first line of the script is
#!/bin/sh
running o/s commands using java
a reader, December 01, 2006 - 9:55 am UTC
Hi Tom,
Regarding available disk space, please see the scripts and the output below. I am using 10g database. The problem I am seeing is that the returned value is not captured. Please advise where is it going wrong.
1. Content of the korn shell script
#!/usr/bin/ksh
df -k /export/data/db1|grep "^/" | awk '{print $4;}'
2. Output of the korn shell script when ran from the unix.
$ /projects/atlas/dba/part/scripts/.temp/dfp
2208752
The above korn shell script returns the size of the file system /export/data/db1 in KBytes.
3. Scripts used:
connect dbauser/dbapassword
drop user rt_test cascade;
create user rt_test identified by rt_test;
grant connect, resource to rt_test;
begin
-- Grant execute permission on dfp to rt_test user.
dbms_java.grant_permission(
'RT_TEST', 'java.io.FilePermission',
'/projects/atlas/dba/part/scripts/.temp/dfp',
'execute');
dbms_java.grant_permission
('RT_TEST',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
end;
/
connect rt_test/rt_test
SQL> l
1 create or replace and compile
2 java source named "Util"
3 as
4 import java.io.*;
5 import java.lang.*;
6 public class Util extends Object
7 {
8 public static int RunThis(String args, String[] cmdOutput)
9 {
10 Runtime rt = Runtime.getRuntime();
11 int rc = -1;
12 String coutput = " ";
13 String ot = " ";
14 try
15 {
16 Process p = rt.exec(args);
17 int bufSize = 4096;
18 BufferedInputStream bis =
19 new BufferedInputStream(p.getInputStream(), bufSize);
20 int len;
21 byte buffer[] = new byte[bufSize];
22 // Echo back what the program spit out
23 while ((len = bis.read(buffer, 0, bufSize)) != -1) {
24 System.out.write(buffer, 0, len);
25 ot = new String(buffer, 0, len);
26 coutput = coutput + ot;
27 }
28 rc = p.waitFor();
29 }
30 catch (Exception e)
31 {
32 System.out.println("Error running command: " + args + "\n" + e.getMessage());
33 e.printStackTrace();
34 rc = -1;
35 }
36 finally
37 {
38 cmdOutput[0] = coutput;
39 return rc;
40 }
41 }
42* }
SQL> /
Java created.
SQL> create or replace function RUN_CMD( p_cmd in varchar2, p_cmd_out out varchar2) return number as
language java
name 'Util.RunThis(java.lang.String, java.lang.String[]) return integer';
/
2 3 4
Function created.
SQL> create or replace procedure RC(p_cmd in varchar2, p_cmd_out out varchar2) as
x number;
begin
x := run_cmd(p_cmd, p_cmd_out);
dbms_output.put_line('Cmd output:' || p_cmd_out);
end;
/
2 3 4 5 6 7
Procedure created.
4. Output from the procedure RC:
SQL> set serveroutput on size 1000000
SQL> execute dbms_java.set_output(1000000)
PL/SQL procedure successfully completed.
SQL> declare
2 r varchar2(4000);
3 begin
4 rc('/projects/atlas/dba/part/scripts/.temp/dfp', r);
5 dbms_output.put_line('Return value:' || r);
6 end;
7 /
Cmd output:
Return value:
PL/SQL procedure successfully completed.
December 01, 2006 - 10:14 am UTC
so, echo somethings out - start simple, add stuff. see what you see.
DEBUG IT.
a reader
a reader, December 01, 2006 - 10:28 am UTC
ok. i have added few println statements as shown in the script below. the output also is shown below. it looks like it is not going inside the while loop. i don't know why.
create or replace and compile
java source named "Util"
as
import java.io.*;
import java.lang.*;
public class Util extends Object
{
public static int RunThis(String args, String[] cmdOutput)
{
Runtime rt = Runtime.getRuntime();
int rc = -1;
String coutput = " ";
String ot = " ";
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
System.out.println("Before the loop. ");
while ((len = bis.read(buffer, 0, bufSize)) != -1) {
System.out.write(buffer, 0, len);
ot = new String(buffer, 0, len);
coutput = coutput + ot;
System.out.println("Within the loop. coutput:" + coutput);
}
System.out.println("Before wait");
rc = p.waitFor();
}
catch (Exception e)
{
System.out.println("Error running command: " + args + "\n" + e.getMessage());
e.printStackTrace();
rc = -1;
}
finally
{
cmdOutput[0] = coutput;
System.out.println("coutput in finally:" + coutput);
return rc;
}
}
}
/
SQL> l
1 declare
2 r varchar2(4000);
3 begin
4 rc('/projects/atlas/dba/part/scripts/.temp/dfp', r);
5 dbms_output.put_line('Return value:' || r);
6* end;
SQL> /
Before the loop.
Before wait
coutput in finally:
Cmd output:
Return value:
PL/SQL procedure successfully completed.
December 01, 2006 - 10:35 am UTC
i meant put DEBUG IN THE SCRIPT.
do a couple of /bin/echo'es in there - touch a file, echo something to a file - prove that the script is running for example.
running os commands using java
a reader, December 01, 2006 - 11:44 am UTC
the korn shell script is now changed to redirect the output to output.txt under the same directory. i ran the script from unix prompt and it did produce the file and contained the expected output. the output.txt file was deleted before running the procedure. after running the procedure, it did generate the output.txt file but it is empty. so it did call the korn shell script. the file size for output.txt as shown below is zero.
Korn shell script dfp:
#!/usr/bin/ksh
df -k /export/data/db1|grep "^/" | awk '{print $4;}' > /projects/atlas/dba/part/scripts/.temp/output.txt
SQL> declare
2 r varchar2(4000);
3 begin
4 rc('/projects/atlas/dba/part/scripts/.temp/dfp', r);
5 dbms_output.put_line('Return value:' || r);
6 end;
7 /
Before the loop.
Before wait
coutput in finally:
Cmd output:
Return value:
PL/SQL procedure successfully completed.
SQL> !ls -lrt /projects/atlas/dba/part/scripts/.temp/
drwxrwxr-- 4 oracle dba 2048 Sep 29 13:46 ..
-rwxrwxrwx 1 oracle dba 120 Dec 1 16:26 dfp
-rw-rw-r-- 1 oracle dba 0 Dec 1 16:30 output.txt
drwxrwxr-- 3 oracle dba 1024 Dec 1 16:30 .
December 01, 2006 - 12:46 pm UTC
maybe it cannot find df and maybe stderr (which is not captured) is saying "no program df"
maybe put an explicit path on df.
running os command using java
a reader, December 04, 2006 - 5:59 am UTC
You were right, it wasn't capturing the error message.
I put the full path for df and it still wouldn't work. So I decided to trap the error message by adding "2> /projects/atlas/dba/part/scripts/.temp/err.txt" at the end of the df command. It correctly showed the error message as "awk:not found". So I put the full path for grep and awk commands in the shell script and it worked like a treat.
I want to thank you very much as you got me to think in the right direction. You are just the best.
replace string by passing parameters in unix script
Lily, December 04, 2006 - 1:52 pm UTC
Tom,
We are write some unix script for our DBA tasks.when I write some unix script to
replace string, I can use sed to accomplish it.
For example, if I want to replase string of REUSE with SET in some text file, I may do:
<dbdev2.ny.sothebys.com:oracle:anetdev:/tmp> cat rp_string.txt
REUSE
<dbdev2.ny.sothebys.com:oracle:anetdev:/tmp> vi t.ksh
#!/usr/bin/ksh
file=/tmp/rp_string.txt
cat rp_string.txt| sed 's/REUSE/SET/' > rp_string.txt.tmp
<dbdev2.ny.sothebys.com:oracle:anetdev:/tmp> chmod u+x t.ksh
<dbdev2.ny.sothebys.com:oracle:anetdev:/tmp> t.ksh
<dbdev2.ny.sothebys.com:oracle:anetdev:/tmp> more rp_string.txt.tmp
SET
But if I want to replace the string by using parameter with $ sign,
how can I do it? For example, I have some ORACLE_SID as 'prd' in the text file,
I want to replace all 'prd' to 'stg' in the text file by passing parameters $SID_1 (represents prd) and $SID_2( represents stg), the way using sed with string won't work. Please see below:
<dbdev2.ny.sothebys.com:oracle:anetdev:/tmp> cat rp_string.txt.2
/db/db02/oradata/prd
/db/db01/oradata/prd
<dbdev2.ny.sothebys.com:oracle:anetdev:/tmp> vi t2.ksh
"t2.ksh" 8 lines, 102 characters
#!/usr/bin/ksh
SID_1=$1
SID_2=$2
file=/tmp/rp_string.txt.2
cat rp_string.txt.2| sed 's/$1/$2/' > rp_string.txt.tmp.2
<dbdev2.ny.sothebys.com:oracle:anetdev:/tmp> chmod u+x t2.ksh
<dbdev2.ny.sothebys.com:oracle:anetdev:/tmp> t2.ksh prd stg
<dbdev2.ny.sothebys.com:oracle:anetdev:/tmp> more rp_string.txt.tmp.2
/db/db02/oradata/prd
/db/db01/oradata/prd
You are not only the expert for ORACLE, but also the expert for unix script,
so could you please help me for it?
Thanks in advance.
December 05, 2006 - 9:30 pm UTC
hey, look at that, I've been promoted....
[tkyte@desktop ~]$ cat ./test.ksh
#!/bin/ksh
echo 'hello world' | sed "s/$1/$2/"
[tkyte@desktop ~]$ ./test.ksh hello bye
bye world
[tkyte@desktop ~]$
excellent answer
Lily, December 06, 2006 - 10:28 am UTC
Tom
You example is very helpful for replace the string. But how about if I want to keep all other stuff in the new file, like
from
/db/db02/oradata/prd
/db/db01/oradata/prd
to
/db/db02/oradata/stg
/db/db01/oradata/stg
Thanks again.
Watch those quotes
Greg, December 06, 2006 - 2:46 pm UTC
Lily - if you didn't catch the change from Tom's example:
you have to use double quotes (") in ksh to get parameter substitution. Your script has single quotes ('). Also - you reference an invalid file in your 'cat' command, and you set variables in your script, but don't use them.
check out this example:
#!/bin/ksh
SID_1=$1
SID_2=$2
file=/tmp/rp_string.txt.2
cat $file | sed 's/$SID_1/$SID_2/' > rp_string.txt.tmp.2
cat rp_string.txt.tmp.2
cat $file | sed "s/$SID_1/$SID_2/" > rp_string.txt.tmp.2
cat rp_string.txt.tmp.2
when I run it:
sands> ./t2.ksh prd stg
/db/db02/oradata/prd
/db/db01/oradata/prd
/db/db02/oradata/stg
/db/db01/oradata/stg
Excellent answer and it solved my problem
Lily, December 06, 2006 - 5:34 pm UTC
Tom and Greg,
Thanks sooooo much for your helps. I was so careless and didn't catch Tom's answer with double quotes -- I still used single quotes when testing. Thanks to Greg pointed it out.
I feel very happy and believe it is the best web site for DBA.
CREATE OR REPLACE AND COMPILE vs. loadjava
Stewart Bryson, December 26, 2006 - 10:26 am UTC
Tom:
I know you're not a Java expert, but I simply cannot find another online resource that discusses Java stored procedures. OTN has relegated it to boutique status, I guess.
What is the difference between defining the class in this manner (create or replace and compile) versus writing a class file and using loadjava to load it to the database? Is the class you've defined here able to be imported in other java stored code?
Thanks.
December 26, 2006 - 9:08 pm UTC
well, loadjava will just typically load bytecode (no source code) and doesn't compile. (normal way to use it)
create or replace and compile takes the source code, compiles it into bytecode and loads the source and bytecode.
loadjava is a standalone command line program, create or replace needs a "sqlplus like environment" to work.
http://asktom.oracle.com/Misc/first-there-was.html that is a book written by the guy that "owns" java in the database here at Oracle.
Thanks Tom
Stewart Bryson, December 26, 2006 - 10:20 pm UTC
I had about 20 follow-up questions, but i decided to just buy the book instead.
Thanks as always.
The Mensah book is excellent
Stewart Bryson, January 04, 2007 - 12:58 pm UTC
I'm only 50 pages in, and it's already worth the money. There's a nice little forward by one Mr. Tom Kyte as well.
Running OS cmd using java
praguefish, January 15, 2007 - 4:54 am UTC
Hi, I get the following error when trying to run the 1st example (usr/bin/ps):
java.lang.CloneNotSupportedException
at java.lang.Object.clone(Object.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at Util.RunThis(Util.java:14)
can anyone help??
java.lang.CloneNotSupportedException
Kuassi Mensah, January 20, 2007 - 2:03 am UTC
> Hi, I get the following error when trying to run the 1st > example (usr/bin/ps):
> java.lang.CloneNotSupportedException
> at java.lang.Object.clone(Object.java)
> at java.lang.Runtime.exec(Runtime.java)
> at java.lang.Runtime.exec(Runtime.java)
> at java.lang.Runtime.exec(Runtime.java)
> at Util.RunThis(Util.java:14)
This looks like a bug; which version of the RDBMS (and therefore Java VM) are you using?
Kuassi,
http://db360.blogspot.com
Java SP vs PL/SQL SP
Priyanka Baxi, February 12, 2007 - 7:50 am UTC
Hi Tom,
I was working on Java Stored Procedure(SP) and comparing it with PL/SQL SP.While executing the respective procedures I found that Java SP takes less time as compared to PL/SQL SP.Could you please explain why it is so?The script that I executed is as follows:
create table test_java_sp as select * from all_objects;
insert into test_java_sp select * from all_objects;
insert into test_java_sp select * from all_objects;
insert into test_java_sp select * from all_objects;
insert into test_java_sp select * from all_objects;
insert into test_java_sp select * from all_objects;
insert into test_java_sp select * from all_objects;
insert into test_java_sp select * from all_objects;
insert into test_java_sp select * from all_objects;
commit;
CREATE OR REPLACE AND COMPILE
java source named "Demo"
as
import java.sql.*;
import oracle.jdbc.driver.*;
import java.util.ArrayList;
public class Demo {
//Call to Stored Procedure To Count The Rows
public static int Ob(){
try{
Connection conn = (new oracle.jdbc.OracleDriver()).defaultConnection();
conn.setAutoCommit(false);
String sql = "SELECT * from test_java_sp";
PreparedStatement prepStatement = conn.prepareStatement(sql);
ResultSet result = prepStatement.executeQuery();
int count1 = 0;
if(result!=null){
while(result.next()){
count1++;
}
result.close();
prepStatement.close();
conn.commit();
conn.setAutoCommit(true);
return count1;
}
else
{
return 1;
}
}
catch(SQLException sqlException){
sqlException.printStackTrace();
return 1;
}
}
}
/
Create or replace FUNCTION Java_Demo return number is language java name 'Demo.Ob() return integer';
/
CREATE OR REPLACE FUNCTION Pl_Demo RETURN NUMBER
AS
CURSOR test_cur IS SELECT * FROM test_java_sp;
test_rec test_cur%ROWTYPE;
count1 NUMBER:=0;
BEGIN
OPEN test_cur;
LOOP
FETCH test_cur INTO test_rec;
EXIT WHEN test_cur%NOTFOUND;
count1:=count1+1;
END LOOP;
CLOSE test_cur;
RETURN count1;
EXCEPTION
WHEN OTHERS THEN
IF test_cur%ISOPEN
THEN
CLOSE test_cur;
RETURN NULL;
END IF;
Raise_Application_Error (-20000,SQLCODE ||SQLERRM);
END;
/
set timing on
set serveroutput on
ALTER SYSTEM FLUSH SHARED_POOL;
ALTER SYSTEM FLUSH BUFFER_CACHE;
ALTER SESSION SET TRACEFILE_IDENTIFIER = 'pl_sql';
VARIABLE pl_count number
CALL Pl_Demo() into :pl_count;
ALTER SYSTEM FLUSH SHARED_POOL;
ALTER SYSTEM FLUSH BUFFER_CACHE;
ALTER SESSION SET TRACEFILE_IDENTIFIER = 'java';
VARIABLE java_count number
CALL Java_Demo() into :java_count;
Print java_count
Print pl_count
Regards,
Priyanka Baxi
February 12, 2007 - 10:52 am UTC
well, you are comparing apples to toasters.
You don't actually do anything of use here - did you trying for example accessing the data??
You would never do this code in real life, in real life a real programmer would
select count(*) from (select ....);
if they needed to count the rows.
the "reason", java is array fetching and you have (due to inefficient plsql coding) removed PLSQL's ability to do that.
In 10g, we just code:
CREATE OR REPLACE FUNCTION Pl_Demo RETURN NUMBER
AS
count1 number := 0;
BEGIN
for x in ( select * from test_java_sp )
loop
count1 := count1+1;
end loop;
return count1;
END;
/
and:
ops$tkyte%ORA10GR2> ALTER SYSTEM FLUSH SHARED_POOL;
System altered.
Elapsed: 00:00:00.31
ops$tkyte%ORA10GR2> ALTER SYSTEM FLUSH BUFFER_CACHE;
System altered.
Elapsed: 00:00:12.87
ops$tkyte%ORA10GR2> ALTER SESSION SET TRACEFILE_IDENTIFIER = 'pl_sql';
Session altered.
Elapsed: 00:00:00.01
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> VARIABLE pl_count number
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> CALL Pl_Demo() into :pl_count;
Call completed.
Elapsed: 00:00:02.56
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> ALTER SYSTEM FLUSH SHARED_POOL;
System altered.
Elapsed: 00:00:00.28
ops$tkyte%ORA10GR2> ALTER SYSTEM FLUSH BUFFER_CACHE;
System altered.
Elapsed: 00:00:07.71
ops$tkyte%ORA10GR2> ALTER SESSION SET TRACEFILE_IDENTIFIER = 'java';
Session altered.
Elapsed: 00:00:00.03
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> VARIABLE java_count number
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> CALL Java_Demo() into :java_count;
Call completed.
Elapsed: 00:00:03.27
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> Print java_count
JAVA_COUNT
----------
451099
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> Print pl_count
PL_COUNT
----------
451099
ops$tkyte%ORA10GR2> set echo off
ops$tkyte%ORA10GR2>
and in 9i, we might use bulk collect - but in ALL RELEASES I WOULD ENCOURAGE YOU (demand actually) that you actually compare something "useful" - no one would write code that does this in real life, benchmarks should reflect what you need to do.
What is difference between this logic and DBMS_SCHEDULER
GopiKrishna, February 15, 2007 - 2:08 am UTC
Hi Tom,
This is an excellent piece of work, but I heard in 10g there is DBMS_SCHEDULER PACKAGE, please explain how it differs with this logic.
Also I want to know whether any of Oracle 9i versions support DBMS_SCHEDULER package
Thanks
February 15, 2007 - 11:48 am UTC
you can use dbms_scheduler in 10g to execute code in the operating system, yes.
A reader, February 15, 2007 - 3:32 pm UTC
Tom,
I need to unzip file from Oracle PL/SQL. I am using java stored procedure from this post.
Zip file is located at UTL_FILE folder /mhsiebeldev/siebel/data/BIDAILY_MH_CUSTADDR_20070214.ZIP.
if I run below commnad from SQL*Plus nothing happens
SQL> exec rc('/bin/tar -xvZf /mhsiebeldev/siebel/data/BIDAILY_MH_CUSTADDR_20070214.ZIP')
PL/SQL procedure successfully completed.
If i run '/bin/ls -ltr' I get the below output.
Looks like I need to give correct path as command will be executed as Oracle system user
Can you please help?
SQL> exec rc('/bin/ls -ltr');
total 424
-rw-r--r-- 1 oracle amontfx 12920 Mar 8 2002 initdw.ora
-rw-rw-r-- 1 oracle amontfx 8385 Mar 9 2002 init.ora
-rw-r--r-- 1 oracle amontfx 1677 Aug 29 2005 initCRMDEV2.ora
-rw-r--r-- 1 oracle amontfx 1514 May 17 2006 initRMANDEV.temp
-rw-r--r-- 1 oracle amontfx 1574 May 17 2006 initRMANDEV.old
-rwSr----- 1 oracle amontfx 1536 May 18 2006 orapwRMANDEV
-rw-r----- 1 oracle amontfx 3584 May 18 2006 spfileRMANDEV.old
-rw-rw---- 1 oracle amontfx 24 May 22 2006 lkRMANDEV
-rw-r----- 1 oracle amontfx 4608 Jun 30 2006 spfileCRMDEV.ora
-rwSr----- 1 oracle amontfx 1536 Sep 7 16:18 orapwCRMDEV
-rw-r----- 1 oracle amontfx 4608 Nov 22 11:01 spfileCRMDEV2.ora
-rw-r----- 1 oracle dba 4608 Jan 29 17:00 spfileCRMDEV20129.bkp
-rw-r----- 1 oracle dba 4608 Jan 29 17:00 spfileCRMDEV0129.bkp
-rw-r--r-- 1 oracle dba 1677 Jan 29 17:00 initCRMDEV20129.bkp
-rw-r----- 1 oracle dba 4608 Jan 30 17:00 spfileCRMDEV20130.bkp
-rw-r----- 1 oracle dba 4608 Jan 30 17:00 spfileCRMDEV0130.bkp
-rw-r--r-- 1 oracle dba 1677 Jan 30 17:00 initCRMDEV20130.bkp
-rw-r----- 1 oracle dba 4608 Jan 31 17:00 spfileCRMDEV20131.bkp
-rw-r----- 1 oracle dba 4608 Jan 31 17:00 spfileCRMDEV0131.bkp
-rw-r--r-- 1 oracle dba 1677 Jan 31 17:00 initCRMDEV20131.bkp
-rw-r----- 1 oracle dba 4608 Feb 1 17:00 spfileCRMDEV20201.bkp
-rw-r----- 1 oracle dba 4608 Feb 1 17:00 spfileCRMDEV0201.bkp
-rw-r--r-- 1 oracle dba 1677 Feb 1 17:00 initCRMDEV20201.bkp
-rw-r----- 1 oracle dba 4608 Feb 2 17:00 spfileCRMDEV20202.bkp
-rw-r----- 1 oracle dba 4608 Feb 2 17:00 spfileCRMDEV0202.bkp
dba 1677 Feb 11 17:00 initCRMDEV20211.bkp
PL/SQL procedure successfully completed.
SQL>
February 16, 2007 - 1:34 pm UTC
put some debug in there please - basic stuff - read this thread - been down this "debug it please" path over and over.
Calculator Command in windows Hangs
A reader, February 28, 2007 - 10:02 am UTC
Tom,
I ran the code you provided and made a call to the calculator application in windows xp.
exec :x := RUN_CMD('C:\windows\system32\calc.exe')
The calc.exe runs but it Hangs. When i kill it at OS level the function completes successfully.
I don't understand what kind of interaction the calculator is asking. I made a batch file :
do_calc.bat
@echo off
c:\windows\system32\calc.exe
When I double click this batch file it calls the calculator.
Please guide me through this?
February 28, 2007 - 3:48 pm UTC
the database is running as a service
the service doesn't have a console, it is running in the background
so, when the service that is the database runs "calc.exe", it is running somewhere off in the ether - it cannot see your console.
A reader, March 02, 2007 - 9:02 am UTC
Hmmm, I understand that. Thanks for a brief explanation.
But then I have another question.
How to call the calculator from a database procedure?
Thank you for your time.
March 04, 2007 - 6:04 pm UTC
why would you want to call a GUI from a stored procedure - what would you possibly accomplish that way?
Java Web service calling C executable on OC4J
Gayatri, March 02, 2007 - 8:05 pm UTC
Tom,
I am looking for a way to expose C executable as a web service using Jdev. So I have created a java class that calls the C executable:
public class JavaInvokeC {
public JavaInvokeC() {
}
public int invoke() throws java.io.IOException,
java.lang.InterruptedException {
String program =
"G:\\public_html\\targetexe.exe 11";
System.out.println("invoking program: " + program);
Process p = Runtime.getRuntime().exec(program);
int exitValue = p.waitFor();
System.out.println("exit val: " + p.exitValue());
return exitValue;
}
}
This code runs fine when I call this method from another class' Main method in Jdev. I am able to convert this java class into a web service and deploy the web service on the standalone OC4J. However the C executable is not being invoked.
I get back a message from the web service as 'Unable to get header stream in saveChanges'.
The method you have described is for executing unix command on a Database server. Is there something similar for OC4J. How can I get OC4J to run the C executable that is invoked by the Java web service?
Any pointers of how I can resolve this problem will help.
Thank you
Gaya3
March 04, 2007 - 12:55 pm UTC
what is "g:"
it is a network drive or something
can you not debug your java - have it print out useful stuff like "checking for file existence, found file, file is executable, attemtping to execute file.... blah blah blah..."
java code
A reader, March 04, 2007 - 3:24 pm UTC
The java code is very useful.
run COMMAND
sam, March 04, 2007 - 3:31 pm UTC
Tom:
Can you use RUN_CMD above to actually run perl or unix shell scripts from PL/SQL and pass parameters from PL/SQL.
FOr example, let us say I have a perl program that creates directories on the fielsystem (mkdir).
Can I have pl/sql read a column value in a table and then do create a directory on the file system /A or /B
If (field='A') then
run_cmd my_perl_program(A);
elsif (filed='B') then
run cmd my_perl_program(B);
END IF;
2. Would the run_CMD work for remote unix server through the web server on the remote machine? Does that perl have to be in the web server directory.
March 04, 2007 - 7:06 pm UTC
you can use run_cmd to pretty much run whatever you can type on the command line, yes.
if you can type:
$ my_perl_program(A)
then yes.
and run cmd will run things on the DATABASE SERVER only
run command
sam, March 04, 2007 - 8:34 pm UTC
Tom:
1. What do you mean by database server only? you mean the file system where the database is running?
2. Is there a way to do it on a remote system if you have a userid/password for the remote machine?
3. or by running a CGI program on the remote machine using a URL with utl_http?
March 05, 2007 - 12:27 pm UTC
1) yes.
2) no, well, that file system would have to be made available to the database server.
3) you would be posting the file, back to square one - right where you started from in the first place.
PL/SQL script for clean-up dump directories
Kamran, April 10, 2007 - 1:19 pm UTC
I wonder is it possible to clean up the bdump and udump directories based on a time parameter !
April 10, 2007 - 3:58 pm UTC
sure it is, not sure I'd use plsql (you'd need to use a bit of java to read the directory...)
if you don't care about them, just limit the max dump size to zero (apparently you don't)
or write a shell script and let cron (or whatever works like cron on your OS) wipe em out.
PL/SQL cycle alert log
kamran, April 10, 2007 - 1:29 pm UTC
Hi,
Could you give me a trick how to clean-up the bdump and udump directories on a time parameter from PL/SQL script !
Reg.
Kamran
April 10, 2007 - 3:58 pm UTC
why do you ask TWICE!?
Appologize
kamran, April 10, 2007 - 5:20 pm UTC
I appologize for it .It was my mistake as I thought, my first submt was unsuccessful. But it was there. I'll be careful next time !
Thanks
Kamran, April 12, 2007 - 11:52 am UTC
wow, great, after setting max_dump_size=0, our problem has been solved.
Thanks again !
utl_file
Kamran, April 16, 2007 - 1:02 pm UTC
I have a slight change in the requirement.
We don't like to use max_dump_size as on some of our databases we need all trace files
without any size specification. We would to just remove trace files after 7 days on all of
our servers ranging from oracle 8 to oracle 10g. Due to a vast rang of databases , we also
don't like to use java inside pl/sql .
This is some sort of management decision to use pl/sql without java and not to use parameter.
Is it possible to use utl_file package for this purpose ! If yes, kindly let me know how to do this. I'm in a horrible condition :)
Thx.
Kamran
April 16, 2007 - 1:41 pm UTC
you need java to read the directory and then, as stated, utl_file can fremove a file.
but you need to know the NAME of the file over 7 days and for that you will write java.
so, I'd probably rather just schedule a cron job and be done with it. A simple FIND command would do this in one line of shell script
you could even use dbms_scheduler in 10g to run said shell script if you wanted.
Regarding JVM Installation
A reader, May 09, 2007 - 2:55 am UTC
Hi Tom,
Our Java team has written Java stored procedures and packaged them in a JAR file.
They use loadjava utility to deploy the jar file in the database.
The deployment would happen from an Application Server and the Java Stored Procedures would be running on Database Server.
They have raised a concern saying that do they need to mention any pre-requisite for using loadjava on Application Server and JSP(JVM installed in database and the version of it).
Database Server Version : 10.2.0.3
Database Client Version : 9.2.0.8
Regards,
Sourabh S Jain
Need Function To Obtain Output
JC, June 05, 2007 - 1:34 pm UTC
Hi Tom
Thanks in advance for the JAVA code.
I have been able to modify your java to use on Windows OS and I was hoping that you could show me some code that calls the java procedure, captures the output into a buffer, and returns that buffer of information in a function call.
Thanks
Just A Thank You
Jim, June 06, 2007 - 2:07 pm UTC
I will look at this info you provided.
Just wanted to say thanks for your patience and guidence
I appreciate your knowledge being shared to folks like me that do not nearly have half the expertise.
Much simpler way to get TZ variable setting
Ron, July 11, 2007 - 2:08 pm UTC
I stumbled across the following method to get the TZ variable that the database was started with rather than having to use java to read the UNIX shell variable:
17:11:21 SQL> connect system@cado
Enter password: *******
Connected.
12:59:52 SQL> select dbms_scheduler.GET_SYS_TIME_ZONE_NAME from dual;
GET_SYS_TIME_ZONE_NAME
---------------------------------------------------------------------
UTC
Elapsed: 00:00:00.05
Too cool.
"sed" not found error when java procedure calls a unix script from oracle database
Ravinder, July 23, 2007 - 2:37 pm UTC
we are getting an error "sed" not found when a java procedure calls a shell script from a database/plsql
below are the steps to call a shell script from java procedure(java procedure inturn called from plsql)
****************************************************
Step1:
create or replace
FUNCTION run_cmd (cmd IN VARCHAR)
RETURN NUMBER
AS LANGUAGE JAVA NAME 'Utils.runScript(java.lang.String) return java.lang.String';
**********************************************************
step 2:
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "Utils" AS
import java.io.*;
import java.lang.*;
public class Utils {
static public int runScript(String cmd)
throws IOException, InterruptedException {
int rv = -1;
Process proc = Runtime.getRuntime().exec(cmd);
InputStream err = proc.getErrorStream();
InputStream outProc = proc.getInputStream();
int nreadErr, nreadOut;
byte[] buf = new byte[1024];
do {
nreadErr = err.read(buf);
if (nreadErr > 0) {
System.err.write(buf,0,nreadErr);
}
nreadOut = outProc.read(buf);
if (nreadOut > 0) {
System.out.write(buf,0,nreadOut);
}
} while (nreadErr>0 && nreadOut>0);
rv = proc.waitFor();
return rv;
}
static public int raiseError(String uxcode, String message)
throws IOException, InterruptedException {
int rv = -1;
String cmdarray[] = new String[7];
cmdarray[0] = "/bin/logger";
cmdarray[1] = "-i";
cmdarray[2] = "-p";
cmdarray[3] = "local0.err";
cmdarray[4] = "-t";
cmdarray[5] = uxcode;
cmdarray[6] = message;
Process proc = Runtime.getRuntime().exec(cmdarray);
rv = proc.waitFor();
return rv;
}
static public String getProperty(String name) {
String val = "";
try {
val = System.getProperty(name);
} catch (Exception excp) {
val = excp.toString();
}
return val;
}
}
************************************************************
we are using 10.2.0 (10g),Solaris 5.10 and oracle application 11.5.10
it is working fine in oracle 9.2.0 and Solaris 5.10
Please let me know what could be the problem for throwing this error.
July 24, 2007 - 9:05 am UTC
you are making assumptions about your environment
your path is not what you think it is, it is the path of the dedicated server.
use fully qualified paths in your script - to avoid trojans, to be sure you are running what you think you should be running, and to avoid this.
Possible side effect
Mahomed Suria, September 11, 2007 - 12:45 pm UTC
I am using the following java stored proc to run a unix shell command through the oracle users job schedule.
CREATE OR REPLACE and COMPILE JAVA SOURCE
NAMED "MyCommand"
AS
import java.io.*;
import java.lang.*;
public class MyCommand extends Object
{
public static int RunThis(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();
// do not leave object lying around, good practice to destroy
p.destroy();
}
catch (Exception e)
{
e.printStackTrace();
rc = -1;
}
finally
{
return rc;
}
}
}
/
I have a possible side effect which is that some processes of the form ora_j.... are being left behind.
e.g
oracle9 15177 1 4 Sep 1 ? 18:47 ora_j000_DB9
oracle9 15115 1 0 Sep 1 ? 9:46 ora_j002_DB9
oracle9 15179 1 0 Sep 1 ? 14:38 ora_j001_DB9
When I examine these processes, they have always run or are running the following sql:
select longdbcs from javasnm$ where short = :1
Any help would be appreciated !!
September 15, 2007 - 3:45 pm UTC
those are just the job queue processes, they will eventually go away, they will be idle (not actually RUNNING that sql, that might have been the last bit they ran) when not executing a job.
Accessing different server through oracle
Shubham, October 04, 2007 - 8:06 am UTC
Hi Tom,
I have a oracle instance in a Unix server (say A) and Informatica instance on another Unix server (say B).
(earlier both were on same server).
I have datafiles comming on B which is manipulated from Pl/Sql procedure on server A.
What should I do in this case.
Do we have something as sharing in Unix, which can suffice my need.
Thanks
preserving/setting env's
Tanya, October 04, 2007 - 1:31 pm UTC
Hi Tom,
I have this whole setup working, but am running into some environment problems.
I have tested the script that I'm calling from my ApEx app and it works fine at the UNIX level as oracle user. However, when it is called thru Apex, most of my PATH is just GONE!!! to system level commands such as wc and grep.
I've tried setting my env in my script but that doesn't seem to do any good.
Any ideas?
Thanks, Tanya.
perl script
A reader, October 08, 2007 - 7:09 am UTC
Dear Tom,
I need to run a perl command thru pl-sql.
BEGIN
dbms_java.set_output(1000000);
rc('/nikhilesh/test.sh');
rc('/usr/bin/perl -p -i -e ''s/Sam/Ram/g'' /nikhilesh/test.dat');
rc('/usr/bin/cat /nikhilesh/test.dat');
END;
test.sh contains
#!/bin/ksh
ls /projects/GLOSSIBaseline/Deployments/DataStream/Reports/ravi
perl -p -i -e 's/Sam/Ram/g' test.dat
cat /nikhilesh/test.dat
All permissions are in place. It doesn'r throw any error.
executes ls and cat properly but dosent change ravi.dat as a result of perl command.
BEGIN
dbms_java.grant_permission('NIKHIL','SYS:java.io.FilePermission','/nikhilesh/*','read,write,execute');
dbms_java.grant_permission
('NIKHIL',
'SYS:java.io.FilePermission',
'/usr/bin/perl',
'execute');
dbms_java.grant_permission
('NIKHIL',
'SYS:java.io.FilePermission',
'/usr/bin/ls',
'execute');
dbms_java.grant_permission
('NIKHIL',
'SYS:java.io.FilePermission',
'/usr/bin/cat',
'execute');
dbms_java.grant_permission
('NIKHIL',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
END;
Could you please help.
Thanks in advance.
Nikhilesh
Rights Issue
BC, October 09, 2007 - 2:14 pm UTC
I am running into invoker vs definer rights issue.
The objective is as follows
"GENERAL" is to house all common utilities. ( We have several users / schemas that use utilities stored in this schema )
"APP" should be able to execute this utility ( Listed below )GRANTEE TYPE_NAME NAME ACTION SEQ ENABLED
--------------- ----------------------------------- ----------------------------------- ----------------------------------- ---------- --------
GENERAL java.lang.RuntimePermission readFileDescriptor 464 ENABLED
GENERAL java.lang.RuntimePermission writeFileDescriptor 444 ENABLED
APP java.io.FilePermission /usr/bin/script1 execute 507 ENABLED
APP java.lang.RuntimePermission readFileDescriptor 505 ENABLED
APP java.lang.RuntimePermission writeFileDescriptor 504 ENABLED
When I log in as "APP" and execute the following
declare
l_num number;
begin
l_num := system_command.run_command('/usr/bin/script1 /usr2/dev/app/out/file_to_process.txt');
end;
/
I get the below message
java.security.AccessControlException: the Permission (java.io.FilePermission /usr/bin/script1 execute) has not
been granted to GENERAL. The PL/SQL to grant this is dbms_java.grant_permission( 'GENERAL', 'SYS:java.io.FilePermission',
'/usr/bin/script1', 'execute' )
at java.security.AccessControlContext.checkPermission(AccessControlContext.java)
at java.security.AccessController.checkPermission(AccessController.java)
at java.lang.SecurityManager.checkPermission(SecurityManager.java)
at oracle.aurora.rdbms.SecurityManagerImpl.checkPermission(SecurityManagerImpl.java)
at java.lang.SecurityManager.checkExec(SecurityManager.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java_util.RunCmd(JAVA_UTIL:32)
-1
In the "GENERAL" schema, I created the following,
create or replace and compile java source named java_util authid current_user as
import java.io.*;
import java.sql.*;
public class java_util
{
public static int RunCmd(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;
}
}
}
create or replace package system_command authid current_user is
function run_command
(
p_command in varchar2
)
return number;
end system_command;
create or replace package body system_command is
function run_command
(
p_command in varchar2
)
return number
as
language java name 'java_util.RunCmd(java.lang.String) return integer';
end system_command;
The shell script contains the following
/usr/bin/script1
================
#!/usr/bin/ksh
GNUPGHOME=/systemadmin/gpg
export GNUPGHOME
/usr/bin/gpg -quite --yes --batch --armor --no-permission-warning -e -r xxx -o yyy $1
Return=$?
When I grant execute on /usr/bin/script1 to "GENERAL" the programs work as expected. I don't want to do that as we have several users / applications that may uses these utilities.
Database Version 10.2
Operating System LinuxTom, Thank you very much your help is highly appreciated.
Thanks
BC, October 17, 2007 - 2:20 pm UTC
CloneNotSupportedException
Asis, October 26, 2007 - 4:32 am UTC
Hi Tom,
I am executing the below procedure as explained above and getting the error:
declare
x number;
begin
dbms_java.set_output(1000000);
dbms_output.enable(1000000);
x:=run_cmd('/home/oracle/upload/ls');
dbms_output.put_line('Returned value='||x);
exception
when others then dbms_output.put_line('Sql error='||substr(sqlerrm,1,250));
end;
/
java.lang.CloneNotSupportedException
at java.lang.Object.clone(Native Method)
at java.lang.Runtime.exec(Runtime.java:543)
at java.lang.Runtime.exec(Runtime.java:491)
at java.lang.Runtime.exec(Runtime.java:457)
at Util.RunThis(Util:11)
Any idea how to resolve this clone not supported exception?
October 29, 2007 - 10:37 am UTC
you know what, that exception block of yours makes me ill.
I
will
never
understand
I will never ever understand why people do that. Time after time after time.
Makes me sick. Makes me frightened for the future of programming.
I refuse to look at anything that has it anymore. I consider when others, not followed by raise, to be a bug. Maybe that is your issue (it isn't, but I refuse to look any further).
Please - tell us why you do that - when others re-print the error and make the error code GO AWAY so no one knows that an error happened.
Why did you waste the keystrokes - what is the thought process behind catching ALL and ANY exception and hiding it?
java.lang.CloneNotSupportedException
Asis, October 29, 2007 - 2:54 am UTC
Hi Tom,
I have been struggling to get this work for weeks now but unable to understand whether my 10.2.0.1.0 version 10g database does not understand the code or i am doing something wrong.
I would appreciate your input on this please..
Thanks,
Asis
October 29, 2007 - 12:52 pm UTC
I cannot reproduce, cut and paste this example from your system for us.
ops$tkyte%ORA10GR2> drop user rt_test cascade;
User dropped.
ops$tkyte%ORA10GR2> create user rt_test identified by rt_test;
User created.
ops$tkyte%ORA10GR2> grant create session, create procedure to rt_test;
Grant succeeded.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> begin
2 dbms_java.grant_permission
3 ('RT_TEST',
4 'java.io.FilePermission',
5 '/bin/ls',
6 'execute');
7
8 dbms_java.grant_permission
9 ('RT_TEST',
10 'java.lang.RuntimePermission',
11 '*',
12 'writeFileDescriptor' );
13 end;
14 /
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2> connect rt_test/rt_test
Connected.
rt_test%ORA10GR2> create or replace and compile
2 java source named "Util"
3 as
4 import java.io.*;
5 import java.lang.*;
6
7 public class Util extends Object
8 {
9 public static int RunThis(String args)
10 {
11 Runtime rt = Runtime.getRuntime();
12 int rc = -1;
13
14 try
15 {
16 Process p = rt.exec(args);
17
18 int bufSize = 4096;
19 BufferedInputStream bis =
20 new BufferedInputStream(p.getInputStream(), bufSize);
21 int len;
22 byte buffer[] = new byte[bufSize];
23
24 // Echo back what the program spit out
25 while ((len = bis.read(buffer, 0, bufSize)) != -1)
26 System.out.write(buffer, 0, len);
27
28 rc = p.waitFor();
29 }
30 catch (Exception e)
31 {
32 e.printStackTrace();
33 rc = -1;
34 }
35 finally
36 {
37 return rc;
38 }
39 }
40 }
41 /
Java created.
rt_test%ORA10GR2> create or replace
2 function RUN_CMD(p_cmd in varchar2) return number
3 as
4 language java
5 name 'Util.RunThis(java.lang.String) return integer';
6 /
Function created.
rt_test%ORA10GR2> create or replace procedure RC(p_cmd in varchar2)
2 as
3 x number;
4 begin
5 x := run_cmd(p_cmd);
6 end;
7 /
Procedure created.
rt_test%ORA10GR2> variable x number;
rt_test%ORA10GR2> set serveroutput on
rt_test%ORA10GR2> exec dbms_java.set_output(100000);
PL/SQL procedure successfully completed.
rt_test%ORA10GR2> exec :x := RUN_CMD('/bin/ls /tmp');
1_62.dbf
1_63.dbf
1_64.dbf
1_65.dbf
executing custom shell script from PL/SQL
Asis, November 08, 2007 - 12:36 am UTC
Hi Tom,
I am trying to execute a custom shell script and not a command. I am giving the SYS:java.io.FilePermission to execute the custom shell script which will call sql loader to load data into table - but this is showing again the following error:
java.lang.CloneNotSupportedException
at java.lang.Object.clone(Native Method)
at java.lang.Runtime.exec(Runtime.java:543)
at java.lang.Runtime.exec(Runtime.java:491)
at java.lang.Runtime.exec(Runtime.java:457)
at Util.RunThis(Util:11)
Returned value=-1
I would appreciate your guidance on this please...
Thanks a lot
It Worked!
Asis, November 08, 2007 - 5:46 am UTC
Hi Tom,
It worked. I replaced java.io.FilePermission with SYS:java.io.FilePermission, as i was giving the permissions from SYS account.
Thanks a lot.
cal shell script from pl/sql proc
kanna, November 13, 2007 - 2:08 am UTC
Thanks Tom for the above java proc to call a script file.......
but is that i have very little knowledge to understand this but i have to get this done as early as possible i mean calling a shell script from plsql .....
i have run successfully the java proc UTIL ..
please find below wht i have done
create or replace and compile
java source named "Util"
as
import java.io.*;
import java.lang.*;
public class Util extends Object
{
public static int RunThis(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;
}
}
}
-------------------------------
create or replace
function RUN_CMD(p_cmd in varchar2) return number
as
language java
name 'Util.RunThis(java.lang.String) return integer';
------------------------------------
create or replace procedure RC(p_cmd in varchar2)
as
x number;
begin
x := run_cmd(p_cmd);
end;
begin
dbms_java.grant_permission
('APPS',
'java.io.FilePermission',
'/usr/bin/ls',
'read, write, execute, delete');
dbms_java.grant_permission
('APPS',
'java.io.FilePermission',
'/usr/tmp/sh',
'read, write, execute, delete');
dbms_java.grant_permission
('APPS',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
end;
---------------------------
variable x number;
set serveroutput on
exec dbms_java.set_output(100000);
exec :x := RUN_CMD('/usr/bin/ls /tmp');
we r getting all the files listed in folder /tmp
but we r unable to do this below where we would like to create a log file using this command
exec :x := RUN_CMD('/usr/tmp/sh tst.sh');
can you pls let us know whts going wrong from our side
November 16, 2007 - 2:15 pm UTC
these are words that scare me to death:
but is that i have very little knowledge to understand this but i have to get
this done as early as possible i mean calling a shell script from plsql .....
translation:
I have no idea what I'm doing.
But this looks like it might do something useful.
I have no idea how it works, or what security implications there might be and I won't take the time to get there.
Please make it do what I mean to do.
your attempt to run a shell script by granting execute on sh to this user opens up the ability to run ANY SHELL SCRIPT AS ORACLE by this user.
that and the "a" and "e" keys are apparently broken on your keyboard.
you'll find you have a permission or environment problem. does /usr/tmp/sh exist. is it executable by the ORACLE process (you should get a cold shudder if the answer is yes hopefully now - now that you understand the rather large hole you've exposed in your system).
I suggest:
if you have 10g, use dbms_scheduler, it can run external processes. And scripts. And if you follow its directions, you stand a chance of securing it a bit too...
execute Unix script from java stored procedure
Krishna Chaitanya, December 08, 2007 - 12:10 pm UTC
Hi Tom,
i used the java stored procedure to execute a unix script from oracle.
but it works only halfway. while trying to FTP the file it doesnt work.while this script works when executed through unix server.
#!/usr/bin/sh
VALUE=`sqlplus -s safari_owner/welcome@colldmqa <<END
rem -------------------
set linesize 80
set arraysize 1
set verify off
set feedback off
rem -------------------
set serveroutput on
whenever oserror exit sql.oscode
whenever sqlerror exit sql.sqlcode
execute safari_owner.SAFARI_UPLOAD_FILE_STATUS;
exit sql.sqlcode;
END`
echo $VALUE
if [ -z "$VALUE" ]; then
echo "No rows returned from database"
exit 0
else
e=`head -1 "$VALUE"|awk '{print $1}'`
ft="ftp_xml_file_new.sh $e"
sh $ft
fi
please help ....the java program and oracle function and procedure works well to execute a simple script like "echo"
let me know if you require the to check the java procedure and oracle funtion and procedure.
its really urgent for me ..
Thanks
Krishna
December 10, 2007 - 10:54 am UTC
well, not any clue for you
since I don't have your entire suite of scripts.
I would suggest perhaps adding some DEBUG to your scripts, so you can see what is and what is not getting executed.
that is where I would start.
trigger executing SP that calls unix script
Krishna Chaitanya, December 10, 2007 - 8:09 pm UTC
Hi Tom,
it was my mistake and i resolved it.
just wanted to know is there any way to create such a tigger from which we can pass values to the procedure that executes Unix script.
Basically your oracle procedure helped me to execute Unix script but i am unable to execute this procedure through trigger (AFTER INSERT ) and take the values as reference in Unix script..
please help me to get this problem resolved.
Thanks in advance.
Krishna
December 11, 2007 - 7:38 am UTC
you just "pass them in"
exec rc('/usr/bin/ps -ef');
just like that.
krishna chaitanya, December 11, 2007 - 10:09 am UTC
Hi Tom,
below is the code of the trigger that i am using to execute the script.but i need the value of the in this procedure.
how to pass values(:new.file_name :new.FILE_UPLOAD_KEY :new.UPLOAD_STATUS_CODE) in the procedure with the help of trigger.
CREATE OR REPLACE TRIGGER safari_owner.safari_upload_trig
AFTER INSERT
ON safari_owner.SAFARI_UPLOAD_REQUEST
REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
dbms_output.enable(1000000);
dbms_java.set_output(1000000);
safari_owner.rc('/usr/bin/sh /home/powermart/krishna/scripts/retry :new.file_name :new.FILE_UPLOAD_KEY :new.UPLOAD_STATUS_CODE');
END;
/
pleae help..
Thanks
Krishna
December 11, 2007 - 11:07 am UTC
concatenate - you build a string....
(careful there, you gave execute on /usr/bin/sh - you can execute ANYTHING, that would not fly on a real production system, quite dangerous)
..../scripts/retry ' || :new.file_name || ' ' || :new.file_upload_key .....
krishna chaitanya, December 11, 2007 - 11:13 am UTC
thanks tom for the great suggesstion.
krishna chaitanya, December 11, 2007 - 5:34 pm UTC
Hi Tom,
i am stuck at one point and need your help very urgently.
Problem: how can i take the output of unix script as a out parameter of the procedure written below that executes the unix script
CREATE OR REPLACE procedure SAFARI_OWNER.RC(p_cmd in varchar2)
as
x number;
begin
x := run_cmd(p_cmd);
end;
/
please suggest.
Thanks in advance
Krishna
One question on this issue
Reader from India, December 12, 2007 - 11:57 pm UTC
Say I have two databases OraDB1 and OraDB2. I have written a Java class in OraDB2. Can I access this class from a Java or PL/SQL procedure in OraDB1. (not through DB LINK)
December 13, 2007 - 9:44 am UTC
by magic?
I mean - come on - without the dblink how do you think this would work.
In theory, you could load the type-4 thin jdbc driver into the database and open a connection to the remote server using a jdbc java program you load into db1 - but that would be "not an easy or smart thing" to do. It would not be able to participate in the same transaction, you'd have to pass a username and password around, ugh.
A database link is the correct approach here.
connection of .net with oracle backend
Krishna Chaitanya, December 14, 2007 - 11:58 pm UTC
Hi Tom,
i really appreciate for the quick response and very useful clues.
again i have a big prob,
basically i have a frontend application from which user generates a file name and this filename entry goes to a table.
now since i have trigger on the same table so this trigger calls the proc and finally proc executes the unix script and it takes around 2-3 hrs to complete this script functionality.
so i wanted to know if i generate the file name from the frontend then i close the frontend window at the same time so will the backgound process will continue its execution or not. because user will generate the file name but he should not wait for the whole backend process to complete. i.e the frontend process should be independent of the backend ..
if this wont work then please propose a solution so that i can get rid of this issue.
Thanks
Krishna
December 17, 2007 - 10:52 am UTC
if you want some stored procedure to run in the background, you would use dbms_job or dbms_scheduler.
If you say you have a SCRIPT that runs in the OS for hours, I would not suggest or even consider running it from a stored procedure - in fact running any script is sort of shaky since you cannot really "professionally interact with the script", it is not like an API (application program interface) subroutine call or anything. If you have a script to run for hours, you'll want to find some other way to do it - not from the database.
use of DBMS_job and dbms_scheduler
A reader, December 17, 2007 - 10:48 pm UTC
Hi Tom,
please explain in brief how can i user dbms_job to run the stored procedure when a row is inserted into the table.
my requirement is like we are inserting a row through frontend using VB.net.
now after a row is inserted the procedure has to run and perform the activity .so how can DBMS_JOB or DBMS_SCHEDULER would be useful.
thanks
Krishna
December 18, 2007 - 1:29 pm UTC
1) this is as brief as I can be
create trigger t after insert on t
declare
l_job number;
begin
dbms_job.submit( l_job, 'proc;' );
end;
/
Just what i was looking for
Dave, January 08, 2008 - 4:28 pm UTC
This thread just helped me a ton.
thanks Tom
Setting sqlplus environment through plsql
Sharon, February 11, 2008 - 12:47 am UTC
Hello Tom,
I have been reading your threads and find them very useful and I get lots of relevant information from them.
I have a question:
I want to use command SET SQLPROMPT <username> when ever a user is logged in. For e.g.: If SCOTT is login to sql plus I want the SQL > to be displayed as 'SCOTT >'. I plan to fire this command in a LOGON Trigger. Is there any work around for this?
I am using Oracle 10g, on windows 2k.
Please help.
Thanks.
February 11, 2008 - 10:16 pm UTC
think about this please...
sqlprompt - there is some variable in memory somewhere in sqlplus, a program, a program you or I could have written.
You want the database to be able to magically "just write to the client memory, execute some code on the client, silently, magically"
that is called a virus.
You would use a login.sql or glogin.sql file on a shared install - that is a script SQLPLUS runs upon startup.
Would you not be very upset if the database could actually reach out and modify memory arbitrarily in your own developed applications?
To Sharon from UAE - Setting sqlplus environment through plsql
A reader, February 11, 2008 - 11:44 am UTC
Thanks Tom
Sharon, February 13, 2008 - 1:10 am UTC
Hi,
As you said writing such a script in java was not good, I understand that, and I agree to it.
As writing script in glogin/login, I had given it a try. In 8i for a reconnect from the same sqlplus screen it was not giving the required result, for 10g I got my desired result.
Thanks for your time and help.
Really Useful Trick !!
Jekyl, March 10, 2008 - 7:56 am UTC
Excellent Article Tom.
Everything worked firne with me excep the final result, I got this error :-
SQL> set serveroutput on size 1000000;
SQL> exec dbms_java.set_output(1000000);
PL/SQL procedure successfully completed.
SQL> exec rc('/usr/bin/ps -ef');
java.lang.ArrayIndexOutOfBoundsException
at Util.RunThis(Util.java:14)
PL/SQL procedure successfully completed.
What may be the reason ?
March 10, 2008 - 11:45 am UTC
ctl-f for the word ArrayIndexOutOfBoundsException on this page and see what you see...
about $path issue - historics ?
Jens Ludwig, April 10, 2008 - 4:53 pm UTC
Good evening,
just a historic question for trying to understand such a path issue i just encountered.
running the same stored procedure on a 9.2 (not set up by me) and a 10g2 (set up by me)it seems to behave different regarding unsetting $PATH in the shell.
9.2 doesnt seem to unset the $PATH but i´m not sure if this is due to slightly differen enviroment setups or if that unset was introduced with oracle 10.
April 10, 2008 - 8:32 pm UTC
I don't know what you are referring to here.
can JAVA stored procedure run commands on client ?
A reader, April 11, 2008 - 3:59 pm UTC
Hi Tom,
Above examples show how to run host commands from database using JAVA stored procedure. The host commands run on the server hosting the database. Is it possible to use same approach to run client commands ?
Assuming "oscmd" is a java stored program in database residing on server X. If i call "oscmd" remotely from a client Y using TNS connection then commands will run on server X. Is there a way to run host commands on client Y from java program in database on server X ? If it is not possible with this approach is there any other way ?
thanks
April 11, 2008 - 4:12 pm UTC
that would be very virus like wouldn't it.
Think about this - you really want a program running on machine X to be able to execute arbitrary code "as some user" (heck, what user?) on some other machine?
No, it will not happen, unless that client machine itself that you want to execute code on HAS A SERVER of some sort, providing a published service that other machines can connect to and run stuff with.
Unix script not executed
Vikram Rathore, April 24, 2008 - 6:21 am UTC
Tom,
I have implemented the code as below:-
begin
dbms_java.grant_permission
('ASR_OWNER',
'java.io.FilePermission',
'/d2/users/rathorv2/*',
'execute');
dbms_java.grant_permission
('ASR_OWNER',
'java.io.FilePermission',
'/u36/app/1SR/v69/*',
'execute');
dbms_java.grant_permission
('ASR_OWNER',
'java.io.FilePermission',
'/usr/bin/*',
'execute');
dbms_java.grant_permission
('ASR_OWNER',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
dbms_java.grant_permission
( 'ASR_OWNER',
'SYS:java.io.FilePermission',
'<<ALL FILES>>',
'execute' );
end;
/
create or replace and compile
java source named "Util"
as
import java.io.*;
import java.lang.*;
public class Util extends Object
{
public static int RunThis(String args)
{
Runtime rt = Runtime.getRuntime();
int rc = -1;
try
{
System.out.println(args);
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;
}
}
}
/
create or replace
function RUN_CMD( p_cmd in varchar2) return number
as
language java
name 'Util.RunThis(java.lang.String) return integer';
create or replace procedure RC(p_cmd in varchar2)
as
x number;
begin
x := run_cmd(p_cmd);
end;
Till this point it's all exactly the same code as given by you.
Now I have created unix scriptt1.sh
#!/bin/sh
/usr/bin/nohup sqlplus asr_owner/XXXXXX @temp.sql > nohup_temp.log &
exit;
temp.sql
d2/users/rathorv2> $cat temp.sql
SET HEAD OFF
SET PAGESIZE 0
SET VERIFY OFF
SET TERMOUT OFF
SET LINE 100
SET WRAP ON
SET FEEDBACK OFF
SET TRIMSPOOL ON
select *
from asr_owner.emp
spool gl_2006_09.csv
/
spool off
exit;
However when I run this it neither generates the log file nor the csv file.SQL> set serveroutput on size 1000000
SQL> exec dbms_java.set_output(1000000);
PL/SQL procedure successfully completed.
SQL> exec rc('/usr/bin/sh /d2/users/rathorv2/t1.sh');
/usr/bin/sh /d2/users/rathorv2/t1.sh
PL/SQL procedure successfully completed.
d2/users/rathorv2> $ls -altr *.log
ls: *.log not found
d2/users/rathorv2> $ls -altr gl_2006_09.csv
ls: gl_2006_09.csv not found
Can you please help me on this. Am I doing something wrong or am I missing some settings
April 28, 2008 - 11:37 am UTC
*environment*
what is "sqlplus", think about this.... where is sqlplus... what sqlplus might you be running (or not) if the environment is not set up....
you are running in someone else's environment! not yours.
how about starting with "echo hello > /tmp/something.txt"
just to see it works, then start debugging from there on up.
Process hangs
Christoph, May 05, 2008 - 6:03 am UTC
Dear Tom,
above "A Reader" was stating that the run_cmd is hanging in a windows environment when running calc.exe. I can understand your doubts about the gui running inside the db service. but when i want to run a program without any gui i face the same problems. in my particular case i want to run sysinternals pskill tool. when i execute it, it creates a new system process pskill and unless i remove this process manually my sql*plus session is blocked.
Is there anyway to accomplish my needs with the run_cmd approach.
Thanks in advance
Christoph
May 05, 2008 - 10:20 am UTC
your pskill is probably waiting on some terminal input/output - and there ISN'T any terminal.
This has to do with the way windows works - undoubtedly here - pskill is waiting for you to type something - and you aren't.
By the way, the database runs with a low privileged user, it is doubtful that it'll work - perhaps that is the problem in the first place - pskill is executed, processed your command line arguments and is saying something like "so sorry, we cannot do that, press enter to continue"
I would discourage this approach, it is not likely you want to kill OS processes from a stored procedure executed in the database - I cannot think of anything good coming from this.
Process hangs
Christoph, May 05, 2008 - 11:47 am UTC
Dear Tom,
our problem in this case is that our customer demnads the database to be the process monitoring system that the application is working transparent over mutliple operating systems. thing is, we are using the run_cmd to start and stop and eventually kill a c++ program which is responsible for tcp/ip communication with plcs. there are times when we need to get rid of the whole process tree (including all threads of the process) if something really bad (on the other side) happens. we know that this is not the way to go as it does not solve the problem, but... anyway - do you think we have a chance to use the run_cmd in a non blocking way? would it help to write a wrapper? what kind of privileges we would need?
thanks in advance
Christoph
May 05, 2008 - 2:52 pm UTC
sorry, but you won't get there from here - i will reiterate a million times: killing a process from a stored procedure sounds like a horrible idea - you should change that "requirement"
You would best be served by creating a "monitoring bit of software - sort of like Oracle has Enterprise manager - to control your processes"
You will not be very successful on windows unless you install the database to run as "your user" which would be beyond a bad idea.
You need the privileges to kill a process on windows - windows would tell you that.
executing custom shell script from PL/SQL
Raj Thangaraj, May 29, 2008 - 1:12 pm UTC
I am trying to execute custom shell script from PL/SQL.
When I run "exec rc('/tmp/putOraclemessage.sh ./test.msg &');", I see this result "PL/SQL procedure successfully completed."
But looks like this is not executed. This script will run a java class.
Please help.
May 29, 2008 - 1:33 pm UTC
you know, that & is sort of "meaningless"
ctl-f for
"you are running a shell specific command"
on this page to see that discussion.
executing custom shell script from PL/SQL
Raj Thangaraj, June 02, 2008 - 9:12 am UTC
I am trying to execute custom shell script from PL/SQL.
These are my permissions. ------------------------------------------------------------------------
begin
dbms_java.grant_permission
('JAVAUSER',
'SYS:java.io.FilePermission',
'/bea/gsipjapps/oracleutility/putOraclemessage.sh',
'execute');
dbms_java.grant_permission
('JAVAUSER',
'SYS:java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
end;
/
------------------------------------------------------------------------
------------------------------------------------------------------------
begin
dbms_java.grant_permission
('JAVAUSER',
'java.io.FilePermission',
'/bea/gsipjapps/oracleutility/putOraclemessage.sh',
'execute');
dbms_java.grant_permission
('JAVAUSER',
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
end;
/
------------------------------------------------------------------------
Here is my custom script named "Utility.sh" . I have given 777 permission to this script.........
------------------------------------------------------------------------
JAVA_HOME=/jdk142_10
export CLASSPATH=${CLASSPATH}:./log4j.jar
export CLASSPATH=${CLASSPATH}:./JavaProject.jar
echo CLASSPATH=${CLASSPATH}
${JAVA_HOME}/bin/java -version
${JAVA_HOME}/bin/java -classpath ${CLASSPATH} -Dlog4j.configuration=file:./OracleUtility_log4j.xml com.gm.gsip.utility.OraclePutJMSMQMessage $1
-----------------------------------------------------------------------
This is the command I use in sql...................
-----------------------------------------------------------------------
exec rc('/bea/gsipjapps/oracleutility/Utility.sh ./input.file &');
-----------------------------------------------------------------------
When I run the exec command, I don't see any errors. But nothing is happening. When I do a exec rc('/usr/bin/ps -ef'); it works!!
Please help!!!!!
June 02, 2008 - 11:44 am UTC
hmmm, one wonders what directory might "." be.
How about this - how about you take 15 steps back and debug this?
eg: put as the beginning of the shell script something like:
#!/bin/sh # tell someone what shell you might be wanting to use
echo Hello World > /tmp/$$.dat
exit
See that you can RUN a script first. Then, move up from there.
Please remember - you don't know what directory you are in (so, you might well need to cd somewhere)
You don't know what your environment is, you have no idea what the classpath is - yet you add to the END OF IT? You should probably just be OVERWRITING it entirely - you have no idea what it might be.
You didn't say what shell to even use - you are not running this from a shell (that is why a default shell might work sometimes there - you run from a shell and that shell says "I am the default", when you run from Oracle there is no default shell there...)
and well, we already covered the & - it is MEANINGLESS IN THIS CONTEXT - get rid of it.
tried this..
Raj Thangaraj, June 02, 2008 - 9:37 am UTC
I tried this and it did not work too..I don't see any errors.
exec rc('sh -c "/tmp/Utility.sh ./test.msg"');
Also I have given this permission
dbms_java.grant_permission
('JAVAUSER',
'SYS:java.io.FilePermission',
'<<ALL FILES>>',
'execute');
dbms_java.grant_permission
('JAVAUSER',
'java.io.FilePermission',
'<<ALL FILES>>',
'execute');
June 02, 2008 - 11:45 am UTC
holy cow
stop, please - do the ctl-f I told you to, use debugging 101 techniques.
but DO NOT RUN SH!!! please think about what that would mean security wise - please
One step closer
Raj Thangaraj, June 02, 2008 - 10:11 am UTC
Looks like finally, my script is getting executed using
exec rc('/usr/bin/sh -c "/tmp/Utility.sh"');
I am trying to run Java in the script. That is not getting executed.
Here is my script
-----------------------------------------------
export JAVA_HOME=/jdk142_10
export APP_PATH=/tmp
export CLASSPATH=${CLASSPATH}:${APP_PATH}/log4j.jar
export CLASSPATH=${CLASSPATH}:${APP_PATH}/JavaProjct.jar
echo JAVA_HOME=${JAVA_HOME}
echo APP_PATH=${APP_PATH}
echo CLASSPATH=${CLASSPATH}
sh -c '${JAVA_HOME}/bin/java -version'
sh -c '${JAVA_HOME}/bin/java -classpath ${CLASSPATH} -Dlog4j.configuration=file:./OracleUtility_log4j.xml com.utility.javautility ./test.msg'
-----------------------------------------------
I am getting the output
JAVA_HOME=/jdk142_10
APP_PATH=/tmp/oracleutility
CLASSPATH=:/bea/gsipjapps/oracleutility/log4j.jar:/bea/gsipjapps/oracleutility/JavaP
roject.jar
--------------------------------
Just my java is not getting executed
June 02, 2008 - 11:56 am UTC
stop it with the /usr/bin/sh - you are as about insecure here as you can be. stop grasping at straws here - do not use the sh that way.
just put #!/usr/bin/sh in the script.
it should be obvious why you are not running java. Why do you presume your environment includes /usr/bin - "sh" is not a command that is there apparently, it is not in your path.
removed sh
Raj Thangaraj, June 02, 2008 - 1:26 pm UTC
Sorry, I removed the sh.
This is my procedure call
exec rc('sh -c "/tmp/utility.sh /tmp/test.msg"');
This is my script, utility.sh
--------------------------------------------------------------
#!/usr/bin/sh
export JAVA_HOME=/jdk142_10
export APP_PATH=/tmp
export CLASSPATH=${CLASSPATH}:${APP_PATH}/log4j.jar
export CLASSPATH=${CLASSPATH}:${APP_PATH}/JavaProjct.jar
echo JAVA_HOME=${JAVA_HOME}
echo APP_PATH=${APP_PATH}
echo CLASSPATH=${CLASSPATH}
echo Filename=${1}
${JAVA_HOME}/bin/java -version
${JAVA_HOME}/bin/java -classpath ${CLASSPATH} -Dlog4j.configuration=file:./OracleUtility_log4j.xml com.javautility ./MQ_dev.properties $1
--------------------------------------------------------------
This is my output in the sql window.
--------------------------------------------------------------
JAVA_HOME=/jdk142_10
APP_PATH=/tmp
CLASSPATH=:/tmp/log4j.jar:/tmp/JavaProjct.jar
Filename=
PL/SQL procedure successfully completed.
--------------------------------------------------------------
Some how the java is not executed. Also the test.msg parameter is not passed to the script. I am able to run the script from unix command line and it works perfectly fine.
I am not sure what mistake I am doing. Please help
June 02, 2008 - 2:34 pm UTC
exec rc('sh -c "/tmp/utility.sh /tmp/test.msg"');
^^^^^^ that is BAD very very BAD do not do that!!!!!
why? because next, I'll just
exec rc('sh -c rm -rf *')
you have given the owner of RC carte blanche on your server.
Still java is not executed
Raj Thangaraj, June 02, 2008 - 4:14 pm UTC
I removed the sh from the proc call.
exec rc('/tmp/utility.sh /tmp/test.msg');
Seeing parameter, but still the java is not getting executed
This is the output
----------------------------------------------
JAVA_HOME=/jdk142_10
APP_PATH=/tmp
CLASSPATH=:/tmp/log4j.jar:/tmp/JavaProject.jar
Filename=/tmp/test.msg
PL/SQL procedure successfully completed.
----------------------------------------------
June 02, 2008 - 5:18 pm UTC
continue debugging....
come on.... you have this:
-------------------------------------------------------
${JAVA_HOME}/bin/java -version
${JAVA_HOME}/bin/java -classpath ${CLASSPATH} -Dlog4j.configuration=file:./OracleUtility_log4j.xml
com.javautility ./MQ_dev.properties $1
-------------------------------------------------------
and it is not running, what might be the first thing you'd think to try to debug this, maybe adding:
ls -lag ${JAVA_HOME}/bin/java
which ${JAVA_HOME}/bin/java
let's see if we can "see" the file (think permissions, you know that script - it isn't running as "you" here.
I can see the file
Raj Thangaraj, June 03, 2008 - 9:17 am UTC
I can see the file. Looks like I have all the permissions.
-----------------------------------------------------------------------
JAVA_HOME=/jdk142_10
APP_PATH=/tmp
CLASSPATH=:/tmp/log4j.jar:/tmp/JavaP
roject.jar
Filename=/tmp/test.msg
-r-xr-xr-x 1 mqm 138936 Jan 17 2006 /jdk142_10/bin/java
-----------------------------------------------------------------------
June 03, 2008 - 12:06 pm UTC
did you do a which on it.
and what does this "java do"
and if this java fails does it write to stdout or stderr
so maybe you need to redirect the output of the java program (both stdout and stderr) and then cat that file
for I only retrieve by design stdout.... (you are free to change that of course, you have all of the code...)
I think I figured
Raj Thangaraj, June 03, 2008 - 9:46 am UTC
Looks like, I cannot call the java execution from the java. I am doing something like
From Java, call Unix shell script
From Shell script, call java again
I tried to run the script using one of my local run command java programs and got back the same result. Looks like I have to do something else(using C may be).
Thanks a lot for your helping this dumbo!!
June 03, 2008 - 12:09 pm UTC
please, that doesn't even begin to make sense.
of course you can execute a program. Java is just a program.
a java stored procedure runs a script.
that script runs programs (you've already shown that it can)
java is just another program - it is not MAGIC, it is not SPECIAL, it just be a program
and one that is probably spewing forth information on stderr which you are not seeing.
so, use redirection to redirect the stdout and sdterr to a file (say /tmp/$$$.java.out) and either cat that file or read it after you are done
Java Mismatch
Raj Thangaraj, June 06, 2008 - 1:45 pm UTC
Oracle is using Java 1.3. But I have Java 1.4 installed in the box and using it(I cannot use Java 1.3). Would that be the difference
This is my call
-----------------------------
exec rc('/tmp/Utility.sh /tmp/test.msg > /tmp/cat.out');
-----------------------------
This is my Utility.sh script
------------------------------------------------
#!/usr/bin/sh
export JAVA_HOME=/jdk142_10
export APP_PATH=/tmp
export CLASSPATH=${CLASSPATH}:${APP_PATH}/log4j.jar
export CLASSPATH=${CLASSPATH}:${APP_PATH}/JavaProjct.jar
echo JAVA_HOME=${JAVA_HOME}
echo APP_PATH=${APP_PATH}
echo CLASSPATH=${CLASSPATH}
echo Filename=${1}
ls -lag ${JAVA_HOME}/bin/java
${JAVA_HOME}/bin/java -version > ${APP_PATH}/cat1.out
${JAVA_HOME}/bin/java -classpath ${CLASSPATH} -Dlog4j.configuration=file:${APP_PATH}/Utility_log4j.xml com.gm.gsip.utility.OraclePutJMSMQMessage ${APP_PATH}/MQ_dev.properties $1 > ${APP_PATH}/cat2.out
----------------------------------------
When I run it, cat1.out & cat2.out is empty. I don''t see a file cat.out
What am I doing wrong?
Stewart Bryson, June 07, 2008 - 11:28 pm UTC
The JVM seems to want unlimited permissions.
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bi
PL/SQL Release 10.2.0.3.0 - Production
CORE 10.2.0.3.0 Production
TNS for Linux: Version 10.2.0.3.0 - Production
NLSRTL Version 10.2.0.3.0 - Production
5 rows selected.
Elapsed: 00:00:00.21
SQL>
SQL> EXEC dbms_java.grant_permission('RT_TEST','java.io.FilePermission','/bin/ls','execute');
PL/SQL procedure successfully completed.
Elapsed: 00:00:04.12
SQL>
Output from buffer 'qwer2.sql':
SQL> EXEC dbms_java.grant_permission('RT_TEST','java.lang.RuntimePermission','*','writeFileDescriptor' );
PL/SQL procedure successfully completed.
Elapsed: 00:00:01.98
SQL>
Output from buffer 'qwer2.sql':
SQL> connect rt_test/rt_test@dtdinc1
Connected.
SQL>
SQL>
SQL> create or replace and compile
2 java source named "Util"
3 as
4 import java.io.*;
5 import java.lang.*;
6
7 public class Util extends Object
8 {
9 public static int RunThis(String args)
10 {
11 Runtime rt = Runtime.getRuntime();
12 int rc = -1;
13
14 try
15 {
16 Process p = rt.exec(args);
17
18 int bufSize = 4096;
19 BufferedInputStream bis =
20 new BufferedInputStream(p.getInputStream(), bufSize);
21 int len;
22 byte buffer[] = new byte[bufSize];
23
24 // Echo back what the program spit out
25 while ((len = bis.read(buffer, 0, bufSize)) != -1)
26 System.out.write(buffer, 0, len);
27
28 rc = p.waitFor();
29 }
30 catch (Exception e)
31 {
32 e.printStackTrace();
33 rc = -1;
34 }
35 finally
36 {
37 return rc;
38 }
39 }
40 }
41 /
Java created.
Elapsed: 00:00:02.54
SQL>
SQL> create or replace
2 function RUN_CMD(p_cmd in varchar2) return number
3 as
4 language java
5 name 'Util.RunThis(java.lang.String) return integer';
6 /
Function created.
Elapsed: 00:00:00.42
SQL>
SQL> create or replace procedure RC(p_cmd in varchar2)
2 as
3 x number;
4 begin
5 x := run_cmd(p_cmd);
6 end;
7 /
Procedure created.
Elapsed: 00:00:00.17
SQL>
SQL> exec rc('ls -l');
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.34
SQL> exec dbms_java.set_output(1000000);
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.21
SQL> exec rc('ls -l');
java.security.AccessControlException: the Permission (java.io.FilePermission <<ALL FILES>> execute) has not been granted to RT_TEST. The PL/SQL to grant this is dbms_java.grant_permission( 'RT_TEST', 'SYS:java.io.FilePermission', '<<ALL FILES>>', 'execute
' )
at java.security.AccessControlContext.checkPermission(AccessControlContext.java)
at java.security.AccessController.checkPermission(AccessController.java)
at java.lang.SecurityManager.checkPermission(SecurityManager.java)
at oracle.aurora.rdbms.SecurityManagerImpl.checkPermission(SecurityManagerImpl.java)
at java.lang.SecurityManager.checkExec(SecurityManager.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at java.lang.Runtime.exec(Runtime.java)
at Util.RunThis(Util:13)
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.15
SQL>
think I solved it
Stewart Bryson, June 08, 2008 - 6:43 pm UTC
Copying the "ls" program to another directory and then calling that executable did the trick. I guess Java needs some permissions on the holding directory for execution that is not required normally at the command line.
Thanks.
Still can't figure out
Raj Thangaraj, June 11, 2008 - 9:27 am UTC
I am still not able to call the "Java" from the procedure. Oracle is using Java 1.3. But I have Java 1.4 installed in the box and using it(I cannot use Java 1.3). I even changed my java home to use the oracle's jdk
This is my call
-----------------------------
exec rc('/tmp/Utility.sh /tmp/test.msg');
-----------------------------
This is my Utility.sh script
------------------------------------------------
#!/usr/bin/sh
export JAVA_HOME=/jdk142_10
export APP_PATH=/tmp
echo JAVA_HOME=${JAVA_HOME}
echo APP_PATH=${APP_PATH}
echo CLASSPATH=${CLASSPATH}
echo Filename=${1}
ls -lag ${JAVA_HOME}/bin/java
${JAVA_HOME}/bin/java -version > ${APP_PATH}/cat1.out
ls -lag ${JAVA_HOME}/bin/java
----------------------------------------
When I run it, this is my output
----------------------------------------
JAVA_HOME=/u01/app/oracle/product/9.2.0.1/jdk
APP_PATH=/tmp
CLASSPATH=
Filename=/tmp/test.msg
lrwxr-xr-x 1 dba 13 Sep 26 2005 /u01/app/oracle/product/9.2.0.1/jdk/bin/java -> .java_wrapper
lrwxr-xr-x 1 dba 13 Sep 26 2005 /u01/app/oracle/product/9.2.0.1/jdk/bin/java -> .java_wrapper
----------------------------------------
I dont see the output of the command
${JAVA_HOME}/bin/java -version > ${APP_PATH}/cat1.out
cat1.out is empty too. Please help
June 11, 2008 - 9:53 am UTC
I've tried to tell you....
you are capturing STDOUT
you want to see STDERR
please - just from the command line you can see this:
sh-3.00$ java -version > /tmp/x
java version "1.4.2_08"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_08-b03)
Java HotSpot(TM) Client VM (build 1.4.2_08-b03, mixed mode)
sh-3.00$ cat /tmp/x
sh-3.00$ java -version >& /tmp/x
sh-3.00$ cat /tmp/x
java version "1.4.2_08"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_08-b03)
Java HotSpot(TM) Client VM (build 1.4.2_08-b03, mixed mode)
sh-3.00$
do you see how the first redirect - did not redirect - the output was just there on screen, /tmp/x is empty - because java writes to stderr!
see how the second redirect, using the syntax for sh - >& - captured stderr (and standard out) to /tmp/x
Simple command call
Raj Thangaraj, June 11, 2008 - 9:45 am UTC
OK. Here I am not calling the script, but calling the java program. Nothing is showing up
exec rc('/usr/bin/ls -lag /bea/jdk142_10/bin/java')
-------------output-------------------------------------------
-r-xr-xr-x 1 mqm 138936 Jan 17 2006 /bea/jdk142_10/bin/java
PL/SQL procedure successfully ompleted.
-----------------------------------------------------------------
exec rc('/bea/jdk142_10/bin/java -version')
------------------output--------------------------------------
PL/SQL procedure successfully completed.
-----------------------------------------------------------------
I even did this to redirect the output to the file. But this file is not created
exec rc('/bea/jdk142_10/bin/java -version > /tmp/cat4.out')
------------------output--------------------------------------
PL/SQL procedure successfully completed.
-----------------------------------------------------------------
June 11, 2008 - 9:54 am UTC
sigh..... read above
and stop using > in the rc call, we've been over and over and over that. >, &, etc are SHELL things, you are running a program, programs do not understand ">"
From command prompt
Raj Thangaraj, June 17, 2008 - 12:33 pm UTC
From Command Line if i do
usahs245:bea /tmp//jdk142_10/bin/java -version >& /cat.out
I am getting this error:
ksh: /tmp/cat.out: bad file unit number
June 17, 2008 - 2:56 pm UTC
please look up the right commands and syntax for your OS then. Come on, you are using this OS - this is all about interfacing with the shell on your OS, this is pretty basic stuff (redirection, it is what unix is built on - pipes and redirection)
make sure you are using the same interactive shell as you are using in the script in the background...
From Command Prompt
Murali Hatwar, June 24, 2008 - 1:01 pm UTC
All,
Please remember that Runtime.exec() is not a command interpreter.
If you try doing redirection then you will have to handle it from within the javacode using threads for the streams.
It is better if you can put the commands which you run in a .sh or .bat file depending upon your OS and run that when needed instead of running the redirecting commands as a argument to the exec method.
June 24, 2008 - 1:19 pm UTC
yeah, that is what I've been saying over and over...
use redirection to get whatever you want to appear on stdout, and then the little java routine does the rest.
Java source
Nantha, December 02, 2008 - 4:36 pm UTC
Hi Tom,
We have some java code in the database and I would like to view the java source for a particular one (ex EmpManager.java).
Could you please let me know how we can extract that from database?
Thanks,
Nantha
December 09, 2008 - 9:56 am UTC
it depends...
was the *source code* ever LOADED? Most of the time, people load compiled byte code - not the source.
So, was the source loaded?
ops$tkyte%ORA10GR2> select text from user_source where name = 'Util' order by line;
TEXT
-------------------------------------------------------------------------------
import java.io.*;
import java.lang.*;
public class Util extends Object
{
public static int RunThis(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;
}
}
}
37 rows selected.
if you just loaded byte code, we won't have the source of course.
Is this will work with Windows 2000 OS
Gopinath, January 28, 2009 - 8:58 am UTC
Is this will work with windows 2000 OS?
I had tried it.it is creating the Process but it is not actualy runing the exe.
Please help to solve this.
January 28, 2009 - 3:44 pm UTC
how do you know it is not?
and the .exe is not a GUI program correct?
eg: GIVE A LOT MORE DETAIL
yes, this works, even on windoze
More details about what i did
Gopinath, January 28, 2009 - 11:49 pm UTC
I had created the java class as follows
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED MM_ADMIN."MyCommandgi" as
import java.io.*;
import java.lang.*;
import oracle.sql.*;
import java.sql.*;
import java.util.*;
public class MyCommandgi
{
public static oracle.sql.CHAR RunThisgi(String args)throws SQLException
{
Runtime rt = Runtime.getRuntime();
String rc = "ok";
String line;
try
{
String[] finalCommand;
finalCommand = new String[1];
finalCommand[0] = args;
final Process pr = Runtime.getRuntime().exec(finalCommand);
BufferedReader input =new BufferedReader(new InputStreamReader(pr.getInputStream()));
input.close();
}
catch (Exception e)
{
e.printStackTrace();
rc = "IO Exception "+e;
return new oracle.sql.CHAR(rc,null);
}
//finally
{
return new oracle.sql.CHAR(rc,null);
}
}
}
/
Then i had created the function
as follows
CREATE OR REPLACE FUNCTION MM_ADMIN.f_cmd2 (p_command IN VARCHAR2)
return VARCHAR2
AS LANGUAGE JAVA
NAME 'MyCommandgi.RunThisgi(java.lang.String) return oracle.sql.CHAR';
/
finally my calling procedure is
DECLARE
L_MSG VARCHAR2(1000);
BEGIN
L_MSG:=F_CMD2('C:\Program Files\Microsoft Office\Office\excel.exe');
DBMS_OUTPUT.PUT_LINE(L_MSG);
END;
/
this is creating a process in windows but it is not actually opening the excel application
i had give all the java file permission required.
Please help me to open any exe through,oracle procedure.
January 30, 2009 - 1:58 pm UTC
ok, please think about this.
Where will excel "appear" exactly? It has nowhere to "appear", you cannot possibly even consider running a GUI application, it would appear on the database servers 'console' - a thing that doesn't really exist! The server is running as a service, it has no screen.
qustion
mohannad, February 03, 2009 - 6:46 am UTC
Dear Tom,
it was very usefull for me to implent this feature, i followed the steps you mentioned above. it was ok for simple cmd comand like md temp, the folder was created. i neeed to run a program, when i run this comand from cmd its working:
adbulkexport.exe /users /path:cn=users,dc=smsglab,dc=com /samaccountname /userprincipalname /password /givenname /sn /file:c:\mkh.csv
so i but it i batch file and i called this batch file from the procedure rc, its not working. do you have any idea why??
thanks.
JAccelerator in relation to Java?
Stuart, February 10, 2009 - 3:42 pm UTC
Hi Tom,
I installed a new application into a fresh 10.2.0.4 database (front end=MS Server 2003), and noticed shortly afterward that DB Console was displaying an info message in the policy violations recommending I install JAccelerator (NCOMP).
There doesn't seem to be any Java stored procedures in our DB apart from Oracle-related ones.
WTS: SYS AS SYSDBA> select owner, object_type, count(*)
from all_objects
where object_type like '%JAVA%'
group by owner, object_type;
OWNER OBJECT_TYPE COUNT(*)
------------------------------ ------------------- ----------
EXFSYS JAVA RESOURCE 1
ORDSYS JAVA CLASS 1389
MDSYS JAVA CLASS 273
MDSYS JAVA RESOURCE 4
EXFSYS JAVA CLASS 41
SYS JAVA DATA 298
SYS JAVA CLASS 14747
SYS JAVA RESOURCE 704
ORDSYS JAVA RESOURCE 66
9 rows selected.
In fact, the application schema doesn't have much in the way of stored procedures...
WTS: SYS AS SYSDBA> select object_type, count(*)
from all_objects
where owner = 'WTS'
group by object_type;
OBJECT_TYPE COUNT(*)
------------------- ----------
SEQUENCE 85
PROCEDURE 3
PACKAGE 1
PACKAGE BODY 1
TRIGGER 84
VIEW 518
TABLE 212
INDEX 272
8 rows selected.
Questions:
1. I had a quick look at Metalink (Note 452024.1), where it says the NComp utility is to native compile Java code. Does this mean DB Console is just wanting me to install this for the sake of the system-related Java procedures/packages?
2. Metalink Note 134985.1 has info on how to use NComp, but it makes references to 8i (although the modified date is Sep 2008). Is the NComp utility pretty much the same through 9i-11g?
3. Would using NComp to compile java natively result in less memory requirements (i.e. my java_ parameters being set lower), as opposed to not using NComp?
finally clause cannot complete normally
Jim Cox, June 01, 2009 - 3:11 pm UTC
Hi Tom
I have been using the code you supplied for "Util" and I am not sure if this just happened since I went from 9i to 10g, but even though the code compiles with no errors
when i check dba_errors:
TYPE SEQUENCE TEXT ATTRIBUTE MESSAGE_NUMBER
------------ ---------- ------------------------------------------------------------ --------- --------------
JAVA SOURCE 1 Util:35: warning: finally clause cannot complete normally ERROR 0
JAVA SOURCE 2 } ERROR 0
JAVA SOURCE 3 ^ ERROR 0
JAVA SOURCE 4 1 warning ERROR 0
when i check dba_objects:
Owner Object Type Object Name Status Created
------------ ------------------ ------------------------------------ ---------- ---------
LLPROD JAVA CLASS Util VALID 14-FEB-09
LLPROD JAVA SOURCE Util VALID 14-FEB-09
2 rows selected.
any idea if i should be concerned about this warning ?
Thanks For Your Time
June 01, 2009 - 8:22 pm UTC
how about you either very very very explicitly point to the code in question or post it?
this is a very large page.
Util Code
Jim Cox, June 02, 2009 - 12:33 pm UTC
Sorry Tom
here is the code i was referring to
create or replace and compile
java source named "Util"
as
import java.io.*;
import java.lang.*;
public class Util extends Object
{
public static int RunThis(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;
}
}
}
/
Thanks Again
June 02, 2009 - 6:45 pm UTC
Thanks For The Info
Jim Cox, June 05, 2009 - 1:46 pm UTC
just a thank you
Error in executing
Ahmed, June 08, 2009 - 10:24 am UTC
Dear Tom.
After I did steps you mentioned to execute ps command through PL I face the following message
SQL> exec :x := RUN_CMD('/usr/ucb/ps -ef');
java.lang.ArrayIndexOutOfBoundsException
at Util.RunThis(Util:11)
PL/SQL procedure successfully completed.
I use 10.2 database & Redhat AS 3
June 08, 2009 - 1:36 pm UTC
and when you ctl-f'ed for
ArrayIndexOutOfBoundsException
on this very page.... what did you see?
Executing of exec rc('/usr/bin/ps')
Ahmed, June 09, 2009 - 1:51 am UTC
Dear Tom
Command is not executed in the background
Thanks
June 09, 2009 - 10:22 am UTC
of course it isn't, it is obviously run in the foreground, what use would it be to run it in the background - it simply produces output and doesn't do anything (doesn't change anything). So, if you ran it in the background - the output would be produced and immediate "disappeared" - what use could that be???
Good example
A, July 29, 2009 - 10:52 am UTC
Hello Tom,
Take your example, I tried exporting for 2 tables
exec rc('/dboracle/admin/oracle/product/9.2.8/bin/exp my_user/my_user indexes=n statistics=none tables='||'''TABLE1,TABLE2''' || ' file='||'''/dboracle/admin/oracle/data_dump.dmp''' || ' log='||'''/dboracle/admin/oracle/data_log.log''');
but Im getting the error
Connected to: Oracle9i Enterprise Edition Release 9.2.0.8.0 - 64bit Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.8.0 - Production
Export done in US7ASCII character set and AL16UTF16 NCHAR character set
Note: indexes on tables will not be exported
About to export specified tables via Conventional Path ...
EXP-00011: MY_USER.TABLE1, TABLE2 does not exist
Export terminated successfully with warnings.
Specifying one table is working.
exec rc('/dboracle/admin/oracle/product/9.2.8/bin/exp my_user/my_user indexes=n statistics=none tables='||'''TABLE1''' || ' file='||'''/dboracle/admin/oracle/data_dump.dmp''' || ' log='||'''/dboracle/admin/oracle/data_log.log''');
Also is there any way I can show the output of export command on sqlprompt ?
August 03, 2009 - 2:12 pm UTC
export writes to stdout and stderr, you would have to modify the code to redirect both (eg: find a java programmer or read up enough to figure out how to do that)
Good example
A, July 29, 2009 - 10:58 am UTC
Hello Tom,
Instead of "Take your example" it should be read as "Taking your example" in the above question.
Thanks
shell script execution issue
Thanks Tom!, September 01, 2009 - 7:05 pm UTC
Hello Tom,
I am invoking your script from our application (on a different tier) and it works well when I give echo, touch, mv, chmod etc., but when I try to put these in a shell script it does not work. I do have a #!/bin/sh in the script. Any help would be appreciated.
Thanks!
September 02, 2009 - 10:15 am UTC
fully qualify things.
where is your 'touch', what is your path in your environment (your shelled out environment, not YOUR command line, the command line Oracle has).
do a 'which touch' on your system first
and then fully qualify it, eg, on my linux machine I would code
/bin/touch
shell script execution issue
Thanks Tom!, September 02, 2009 - 2:33 pm UTC
Thanks for the hint! It was not an issue with the script at all and with the way I was handling the shell command. Doing as you suggested helped. Thanks again.
java store procedures can't use sun.jdbc.odbc.JdbcOdbcDriver
Kato, January 12, 2010 - 12:57 pm UTC
Java store procedures can't use sun.jdbc.odbc.JdbcOdbcDriver
This is my java class:
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "Trans"
AS import java.io.*;
import java.lang.*;
import java.sql.*;
import oracle.jdbc.driver.*;
import java.util.*;
import oracle.sql.*;
public class Trans extends Object
{
public static String Transfer (String str)
{
System.out.println("BD DSN-ODBC Connection");
try
{
System.out.println("Driver JDBC ODBC");
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
}
catch (ClassNotFoundException e)
{
System.err.println (e) ;
System.exit (-1) ;
}
.....
connDSN = DriverManager.getConnection(dbUrl, cUser, cPassword);
.....
}
}
/
And this is the error:
ORA-29515: exit called from Java code with status 4294967295
java.lang.ClassNotFoundException: sun/jdbc/odbc/JdbcOdbcDriver
What is necesary to use sun.jdbc.odbc.JdbcOdbcDriver and create ODBC connections?
Thanks.
Kato
January 18, 2010 - 3:44 pm UTC
it would need to be loaded into the database, which will work if and only if the jdbc/odbc driver is "pure java"
however, that said, if you have an odbc data source, why wouldn't you just use a database link and query it - you don't need to approach java in any way shape or form here, it would be the hard way to do it.
OS command not running correctly from the procedure
Jay, January 22, 2010 - 7:03 pm UTC
Hi Tom,
I have used your suggestion to create the function as follows.
As sys user, provided the permission to
begin
dbms_java.grant_permission('WATER','java.io.FilePermission','C:\Program Files\ArcGIS\ArcSDE\ora11gexe\bin\sdetable','execute');
dbms_java.grant_permission('WATER','java.lang.RuntimePermission','*','writeFileDescriptor');
end;
/
As user WATER, successfully created the java source.
create or replace and compile
java source named "Util"
as
import java.io.*;
import java.lang.*;
public class Util extends Object
{
public static int RunThis(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;
}
}
}
/
Then created the function.
create or replace function RUN_CMD(p_cmd in varchar2) return number as language java name 'Util.RunThis(java.lang.String) return integer';
Created a procedure to run the sdetable command.
set serveroutput on
CREATE OR REPLACE PROCEDURE runcmd(fcname_cap varchar2)
AS
sql_stmt22 VARCHAR2 (900);
BEGIN
DBMS_OUTPUT.ENABLE (10000000);
sql_stmt22 := 'select RUN_CMD(''sdetable -o alter_reg -V SINGLE -t '||fcname_cap||' -i sde:oracle11g -u trwater -p WATER@gis -N'') from dual';
execute immediate sql_stmt22;
COMMIT;
END runcmd;
/
-----
When I execute the procedure, I get the following.
SQL> exec runcmd('wnetworkvalve')
select RUN_CMD('sdetable -o alter_reg -V SINGLE -t wnetworkvalve -i
sde:oracle11g -u trwater -p TRWATER@nytrgist -N') from dual
PL/SQL procedure successfully completed.
However, it does not execute the procedure.
I have tried using the following sql statement and it works perfectly.
SQL> select RUN_CMD('sdetable -o alter_reg -V SINGLE -t WNETWORKVALVE -i sde:oracle11g -u trwater -p
TRWATER@nytrgist -N') from dual;
RUN_CMD('SDETABLE-OALTER_REG-VSINGLE-TWNETWORKVALVE-ISDE:ORACLE11G-UTRWATER-PTRW
--------------------------------------------------------------------------------
0
ArcSDE 9.3 for Oracle11g Build 546 Thu Sep 18 12:35:50 2008
Attribute Administration Utility
-----------------------------------------------------
Table WNETWORKVALVE's registration successfully altered.
Can you please tell me why doesn;t it work, when I run the procedure using the RUN_CMD function?
Thanks,
Jay
January 25, 2010 - 5:54 am UTC
because you 'execute' the statement, but never 'fetch' it. You didn't actually run it.
...
sql_stmt22 := 'select RUN_CMD(''sdetable -o alter_reg -V SINGLE -t
'||fcname_cap||' -i sde:oracle11g -u trwater -p WATER@gis -N'') from dual';
execute immediate sql_stmt22;
....
that should just be:
is
n number;
begin
n := run_cmd( 'sdetable .... ' || fcname_cap || ' -i ......' );
end;
No dynamic SQL necessary nor desired.
and definitely, absolutely NO COMMIT - that commit is worse that useless, it is quite harmful (and WRONG)
Ignore the username, password and database name in my last post
Jay, January 22, 2010 - 7:47 pm UTC
In my last post, there is a discrepancy of username, password and database contained in the procedure and the sql statement executed at the end. There is a typo and the username, password and db name is actually same.
Olga, January 26, 2010 - 10:31 am UTC
Tom, I have been trying this solution in 11.1.0.6.0, but unfortunatelly I am getting "ORA-03113: end-of-file on communication channel" error when executing " exec rc('/bin/df -k');". The same solution works in 10.2.4.0. Do you know of any issues with 11g?
January 29, 2010 - 2:40 pm UTC
Please utilize support for that, most likely a networking configuration issue (3113 many times is). No issues that I'm aware of.
pricedure doesn't work
Mauricio Rossetto, March 01, 2010 - 2:52 pm UTC
Hi Tom,
I'm trying to run a simple OS command, but it doesn't work.
This is my step to step:
1) java source compiled:
create or replace and compile java source named util as
import java.io.*;
import java.lang.*;
public class Util extends Object
{
public static int RunThis(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;
}
}
}
/
2) function compiled:
create or replace function RUN_CMD(p_cmd in varchar2) return number
as
language java
name 'Util.RunThis(java.lang.String) return integer';
/
3) procedure compiled:
create or replace procedure RC(p_cmd in varchar2)
as
x number;
begin
x := run_cmd(p_cmd);
end;
/
when I run for example:
SQL> exec rc('ls -la /home/oracle');
PL/SQL procedure successfully completed
The procedure is completed, but it not shows the output.
What do I need to the procedure shows the output?
Thanks
March 02, 2010 - 7:10 am UTC
maybe
rt_test@DEV816> set serveroutput on size 1000000
rt_test@DEV816> exec dbms_java.set_output(1000000)
as above??
ops$tkyte%ORA10GR2> set serveroutput on size 1000000
ops$tkyte%ORA10GR2> exec dbms_java.set_output(1000000)
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2> exec rc('ls -la /tmp');
total 12704
drwxrwxrwt 61 root root 12288 Mar 2 08:10 .
drwxr-xr-x 30 root root 4096 Mar 1 07:41 ..
drwxrwxrwt 2 root root 4096 Mar 1 07:42 .font-unix
drwx------ 3 tkyte tkyte 4096 Mar 1 07:42 gconfd-tkyte
procedure doesn't work part 2
Mauricio Rossetto, March 02, 2010 - 11:00 am UTC
Thanks for your help;
I have called the function as: call dbms_java.set_output(1000000);
But, it should be executed as: exec dbms_java.set_output(1000000)
So, I have another doubt:
I'm trying to call a shell script, but it doens't work fine.
Steps:
SQL> exec rc('/home/oracle/insert_tmp3.sh');
PL/SQL procedure successfully completed
The insert_tmp3.sh file has the following code:
#!/bin/bash
ls -la /home/oracle
So, my question is: Should it shows the output?
Thanks again
March 02, 2010 - 12:49 pm UTC
ctl-f and read about shell scripts and issues with them on this page, it is all here already.
differences between Oracle versions?
Franky, May 01, 2010 - 1:49 am UTC
Hello Tom,
I have just experienced, the following:
- whenever I call a java stored procedure with '/usr/bin/env' on 9.2.0.8 (SPARC Solaris 10) then I basically get the Unix oracle user profile,
- but if I do the same call on 10.2.0.4 (SPARC Solaris 10) then the output/result cannot be associated with the user's profile, since a lot of extra variables are there, but for example the PATH is empty.
Do you know the reason behind this? Is there a way to force 10g to use the variables defined in the user's profile whenever a java call is spawned on the OS level?
Thanks!
May 06, 2010 - 10:34 am UTC
No, there never was - it didn't really change between 9 and 10, what changed was the way you connected.
Say you connect using:
sqlplus scott/tiger
No tns entry, no network. The what happens is your dedicated server is created (forked()) by your SQLPLUS process. the environment of your dedicated server is INHERITED from your sqlplus process. The environment your dedicated server (and hence a java stored procedure) sees is based on the "end users" environment.
Now, suppose (same database!!) you use:
sqlplus scott/tiger@database
You use the network and further assume this connect is made using DEDICATED server again. The environment your dedicated server gets this time COMES FROM THE LISTENER. Not from you - from the listener. Because the listener forks the dedicated server.
Now, support (same database!!! same listener!!!!!) you use:
sqlplus scott/tiger@database_using_shared_server
You connect to the same database, same listener - but use shared server. now your server process gets it's environment NOT FROM YOU, NOT FROM THE LISTENER but from the database software account, since it is forked by the DATABASE instance.
Same database, same software - at least THREE environments possible...
which leads me to the point:
never ever rely on defaults. Your script should explicitly set the EXACT path it needs every single time and further, it should NOT rely on the path for finding programs to execute, it should explicitly call them out - fully qualified - every time, to avoid confusion and to avoid trojan horse programs.
Every single time.
interesting...
Franky, May 10, 2010 - 3:57 pm UTC
Hello Tom,
I didn't mention that in my examples I was connected to dedicated severs via tns and the Oracle 10g environment is RAC. According to your words : this case the environment comes from the listener, but for some reason this does not apply here. Let's see the differences:
Oracle Unix user .profile (Oracle 9i environment)oracle$ env | grep -w PATH
PATH=.:/usr/local/bin:/usr/ccs/bin:/usr/bin:/etc:/usr/openwin/bin:/home/oracle/OraHome9i/bin
Oracle 9i listener environment (Unix level):oracle$ ps -ef | grep -v grep | grep LISTENER
oracle 14076 1 0 Mar 08 ? 52:50 /home/oracle/OraHome9i/bin/tnslsnr LISTENER -inherit
oracle$ pargs -e 14076 | grep -w PATH
envp[2]: PATH=.:/usr/local/bin:/usr/ccs/bin:/usr/bin:/etc:/usr/openwin/bin:/home/oracle/OraHome9i/bin
Oracle 9i java process environment (Unix level) connected as user@tns from remote client:select oscmd('/usr/bin/env') from dual;
PATH --> PATH=.:/usr/local/bin:/usr/ccs/bin:/usr/bin:/etc:/usr/openwin/bin:/home/oracle/OraHome9i/bin
Everything looks good in 9i, PATH variable contents are the same. Let's check 10g:
Oracle Unix user .profile (Oracle 10g environment)oracle$ env | grep -w PATH
PATH=/u01/app/oracle/product/10.2.0/db_1/bin:/u01/app/oracle/product/10.2.0/db_1/OPatch:/usr/sbin:/usr/ccs/bin:/usr/bin:
Oracle 10g listener environment (Unix level):oracle$ ps -ef | grep -v grep | grep LISTENER
oracle 13524 1 0 Apr 30 ? 0:21 /u01/app/oracle/product/10.2.0/db_1/bin/tnslsnr LISTENER_TST-RAC1 -inherit
oracle$ pargs -e 13524 | grep -w PATH
envp[7]: PATH=/u01/app/oracle/product/10.2.0/db_1/bin:/usr/bin:/usr/sbin:/usr/bin
Oracle 10g java process environment (Unix level) connected as user@tns from remote client:select oscmd('/usr/bin/env') from dual;
PATH is empty --> PATH=
PATH is different in all cases. I'm still wondering how could this happen.
I've tried to log on as local user (first case on your list), but no luck -> PATH is empty there as well.
I agree, the best is to implement fully qualified access to the commands in the scripts. My only excuse is that I've inherited these environments with hundreds of shell and perl scripts at the beginning of the migration project...
Any thoughts?
Thanks!
May 10, 2010 - 7:19 pm UTC
The bottom line - the only thing *repeat: the ONLY THING* you need to take away from this is.....
Never rely on defaults
Do not rely on the path
Use explicit paths - be precise, specific
Set your own path if need be, but if you want to write secure code, you will not rely on the PATH ever - even if YOU set it.
You know that
a) the path can be different
b) the path will be different
c) that it is by design that this is "so"
so, there you go - the path is outside of your control, always has been, always will be.
You have some P1 bugs to fix.
...
Oracle 9i java process environment (Unix level) connected as user@tns from remote client:
.......
how did you arrive at that conclusion? That path looks a lot like the listeners path - doesn't it. It looks like the path the listener decided to let the child process inherit - a setting you do not have control over.
Runtime.getRuntime doesn't pass client NLS_LANG on SUN Solaris
Luiz Noronha, June 04, 2010 - 8:02 am UTC
Hi Tom,
I'm calling the following code as most DBAs here do and my profile sets the NLS_LANG to PORTUGUESE_BRAZIL.WE8ISO8859P1.
When I execute it I pass the string:
/ora10g/product/10.2.0/bin/sqlldr sati_loader/xxxx@SATPT1 control='/satwork_01/SATI_PRD/SATI_INTERFACENAOSAP/TXT/tmp/lfnfsc_mr20100514.ctl' log='/satwork_01/SATI_PRD/SATI_INTERFACENAOSAP/TXT/tmp/lfnfsc_mr20100514.log' bad='/satwork_01/SATI_PRD/SATI_INTERFACENAOSAP/TXT/lfnfsc_mr20100514.bad' errors=1000000
Everything goes fine except from the accentuation that goes all wrong to the tables. Santo André for instance is inserted as Santp Andr¿.
I'm presuming that the child process doesn't pass the client's canfiguration on.
Would you help me?
Thanks you.
public class jOSExec extends Object
{
public static int Run(String args) throws Exception
{ Runtime rt = Runtime.getRuntime();
int rc = -1;
String strexec[] = new String[3];
if (args == null) {
System.err.println("Syntax error - Usage: Run <OS command>");
rc = -1; }
else {
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 (IOException e) {
System.err.println("Command " + args + " not found");
throw e;
}
catch (Exception e) {
e.printStackTrace();
System.err.println( e);
throw e;
}
}
return rc;
}
}
June 09, 2010 - 7:18 am UTC
why not replace /ora10g/product/10.2.0/bin/sqlldr with /path/to/my/100%/assured/to/be/correct/as/far/as/environments/go/script
? Calling a binary directly is asking for trouble - you want to make sure the environment is 100% what you think it should be, could be, will be. You have no control over it any other way.
And bigger question for you - why isn't this just:
insert into my_table select * from external_table;
why are you using this legacy, 1990's approach? If you used just sql, you'd be able to catch and handle all errors, have less code, run faster, run safer (in fact I can only think of POSITIVE things here)
You should not be using sqlldr at all - use an external table. Even if you are loading into a remote database (not clear here), just use an external table and a database link. No more passwords passed around (you are as insecure as you can be, I can see your password if I can ps your system)
sudo with RHEL5 and 11g
C, September 28, 2010 - 5:09 am UTC
Hi Tom. I use a java stored procedure to call a shell script which collects various data files and burns the data to a CD so the customer can backup the necessary data easily.
The initial environment was Solaris 8 and 10g. When we moved to RHEL4, the scripts required some minor changes including the need to perform sudo to burn the CD (the java stored procedure would return an error when executing cdrecord as anyone other than root even though the script would run properly if called from a shell of the user--I chalked it up to a peculiarity of the system).
Now with a move to RHEL5 with 11g, sudo does not execute properly. I believe I have all the permissions correctly set for the JVM and filesystem. I modified the script to only perform another executable within the same directory:
/usr/bin/apropos cdrecord
echo $?
the command returns the proper results:
cdrecord (1) - record audio or data Compact Disks or Digital Versatile Disks from a master
cdrecord (rpm) - A command line CD/DVD recording program.
0
However, if I change the script to perform:
/usr/bin/sudo -l
echo $?
it returns only the following:
1
If I run the script in the user shell, it returns the proper response:
User xyz may run the following commands on this host:
(root) NOPASSWD: /usr/bin/cdrecord
0
The file permissions on the executables are standard:
---s--x--x 2 root root 150960 Apr 14 2009 /usr/bin/sudo
-rwxr-xr-x 1 root root 1786 Jul 13 2006 /usr/bin/apropos
Other executables such as ping (which has the sticky bit set as well) work as I expect. Is there something different about executing sudo within the script as apposed to other executables with RHEL5 and 11g? Any ideas why one executable will work and another will not? Am I missing something? Any help would be greatly appreciated.
Thank you.
-C
September 28, 2010 - 8:38 am UTC
... (the java stored procedure would return an error when executing cdrecord
as anyone other than root even though the script would run properly if called
from a shell of the user--I chalked it up to a peculiarity of the system). ...
you shouldn't - the script is running "as oracle" - it is likely the oracle software account (the account the database is running as) did not have the permissions necessary to burn. You should not use root, that is pretty "powerful"
The environment the script is in when you run it from the java stored procedure - it is in the environment of the server - not your user account.
I would start by having the script print out as much information about the environment as possible - id, env, etc - and replicating that environment and testing there (not just in any old user account)
get far far far away from sudo in this context and fix the original issue - the access to the cd.
sudo with RHEL5 and 11g
C, September 28, 2010 - 9:33 am UTC
Hello Tom. Thank you for the response. I'm sorry, I wasn't clear about the user. It is not any user on the system. The system configuration has the listener execute as a different OS user than oracle. I noticed in Solaris the script executed as oracle, whereas in Linux, it executes as the listener account. Actually upon further review, in Linux, whoami and id shows the listener account, but the USER and LOGNAME environment variables show oracle. Is there a way for the java stored procedure to execute as oracle (which would be shown by id)?
I will continue to try to replicate the exact same environment in a shell and the java stored procedure call.
Thank you very much.
-C
September 28, 2010 - 10:52 am UTC
You do not want the OS executable to execute as Oracle - what you have is *perfect* security wise - absolutely PERFECT.
Now, just get the user that runs the listener the minimal set of privileges necessary to do what you want - and then you are set.
do not use root.
do not get this to use the oracle OS account.
use a minimally priveleged OS account as you are - and give it just the smallest amount of rights to do what you need.
sql trace in java program
KG, March 04, 2011 - 10:35 am UTC
Hi Tom
Please let me know ,how to enable sql_Trace from java program?
March 04, 2011 - 11:34 am UTC
just execute this plsql block:
begin dbms_monitor.session_trace_enable( waits => true, binds => true ); end;
or use a statement to execute alter session ....
Doubt about java procedure
Sergio Coutinho, July 10, 2011 - 12:15 am UTC
Hi Tom,
Following the examples of this forum, I developed a java prodedure to remove files from an especific directory of the OS file system (Unix Solaris).
I assign permissions (dbms_java.grant_permission) to a specific directory that already had files. I could successfully remove some of these files.
However, I realized that new files added to the directory are not removed by the java procedure. No error occurs in executing the java procedure and I'm sure there is no OS file permission problem with the new file stored in the OS.
Could tell me what am I doing wrong? Did need - for example - to reassign permissions (ms_java. grant_permission) every time i add new files in this directory?
Best regards,
Sergio
July 12, 2011 - 7:15 am UTC
no example, nothing to see, therefore - no real comment.
Probably, the new files were created with a different default umask applied to them and the user the java stored procedure runs as isn't allowed to erase those files. Since we don't know what api you used to erase files, how you handled (or not) errors - we cannot comment.
If you code is more than 50 lines, it is too long, make your example TINY, SHORT, and reproducible. Tell us exactly what to do to reproduce your issue and make your code TINY TINY TINY (to erase a bunch of files in a directory should be tiny - don't need any real error handling or anything - just let all exceptions propagate up - that'll probably show you what the error is in the first place)
Java Error
A reader, July 15, 2011 - 6:02 pm UTC
Tom:
I want to test your java routine to run unix ZIP command for HTML files that get generated
using UTL_FILE (9i) and then download the zip file to user using PL/SQL
Do you know what is the issue here? Do i need to be a diff user to grant access to my own oracle acount.
tipsadmin@TIPS9i> begin
2 dbms_java.grant_permission
3 ('TIPSADMIN',
4 'java.io.FilePermission',
5 '/usr/bin/ls',
6 'execute');
7
8 dbms_java.grant_permission
9 ('TIPSADMIN',
10 'java.lang.RuntimePermission',
11 '*',
12 'writeFileDescriptor' );
13 end;
14 /
begin
*
ERROR at line 1:
ORA-29532: Java call terminated by uncaught Java exception:
java.lang.SecurityException: policy table update SYS:java.io.FilePermission, /usr/bin/ls
ORA-06512: at "SYS.DBMS_JAVA", line 0
ORA-06512: at line 2
July 18, 2011 - 10:16 am UTC
have your DBA run that, you are not privileged enough to make that grant.
java
A reader, July 18, 2011 - 10:54 am UTC
Tom:
ok, thanks but let me confirm something bfore I ask him.
Would the above statement exacly allows me to run the ZIP or any other unix command or do I need to change it somehow to specify the unix directory where I will need the ZIP command to run?
What oracle privs you need to run the above? I have another instance with DBA privs and still would not run.
DBMS_Scheduler Example
David Aldridge, July 28, 2011 - 3:07 am UTC
Here's a quick example of the sort of code that lets you use DBMS_Scheduler for executing external procedures.
BEGIN
dbms_scheduler.create_job(
job_name => 'ZIP_FILE_JOB',
job_type => 'EXECUTABLE' ,
job_action => '/usr/bin/zip',
number_of_arguments => 2 ,
start_date => NULL ,
repeat_interval => NULL ,
end_date => NULL ,
enabled => TRUE ,
auto_drop => FALSE,
comments => NULL);
END;
/
create or replace procedure zip_file(
zip_file_name varchar2,
source_file_name varchar2,
use_current_session boolean default true)
Is
Begin
dbms_scheduler.set_job_argument_value(
job_name => 'ZIP_FILE_JOB',
argument_position => 1,
argument_value => zip_file.zip_file_name);
dbms_scheduler.set_job_argument_value(
job_name => 'ZIP_FILE_JOB',
argument_position => 2,
argument_value => zip_file.source_file_name);
dbms_scheduler.run_job(
job_name => 'ZIP_FILE_JOB',
use_current_session => zip_file.use_current_session);
end zip_file;
/
java
sam, August 18, 2011 - 8:59 am UTC
Tom:
There is one database where the java stuff works fine.
Unfortunately that is not the database I need to run the ZIp from.
What grants does the oracle account need to run the O/S command using java? Is it
JAVAUSERPRIV
JAVASYSPRIV
JAVA_ADMIN
call dbms_java.gratn_permission
etc.
I was trying to find out from the database where everything works fine using
select * from user_role_privs;
select * from user_sys_privs
but I could find anything.
August 23, 2011 - 2:55 am UTC
ctl-f on this page for dbms_java.grant_permission
complete and full and working example is there with the minimum privileges you need
java
A reader, August 23, 2011 - 8:03 am UTC
<<have your DBA run that, you are not privileged enough to make that grant. >>
1) If DBA did a grant execute on DBMS_JAVA to SCOTT, would i be able to run all those commands myself?
or what ROLES or PRIVILEGE I need so i can run this myself as "SCOTT".
Would the role "JAVASYSPRIV" allow that.
begin
2 dbms_java.grant_permission
3 ('SCOTT',
4 'java.io.FilePermission',
5 '/usr/bin/zip',
6 'execute');
7
8 dbms_java.grant_permission
9 ('SCOTT',
10 'java.lang.RuntimePermission',
11 '*',
12 'writeFileDescriptor' );
13 end;
14 /
August 30, 2011 - 3:13 pm UTC
1) no, you cannot grant yourself something like that - you'd have to be using an account with the privileges to grant the necessary stuff.
Think about this:
you can run the grant command right? (you can run dbms_java)
but you cannot grant yourself just anything you want using grant, can you. That would be an OBVIOUS problem.
think about this.
Do NOT use the extremely deprecated and way far overprivileged javasyspriv. Have the dba grant you just what you need. Security counts.
ZIP files
A reader, September 20, 2011 - 9:37 pm UTC
Tom:
I have an HTML web form (pl/sql & mod_plsql) where users can enter a search criteria, hit "find" and the system will search the ORDERS table (oracle 9i) and list a webpage with all the orders that were found. The user should be able to hit "Zip & Download" button which will dump each ORDER HTML page to a directory on the server, then ZIP all the files together and download ONE zip file to the user client machine. The download can be using a direct link to the server or using mod_plsql.
I am using the above java stored procedure to call the UNIX zip command described in this link. so i cant use a table design solution where files are uploaded to a table and download from a table.
http://www.ehow.com/how_5056873_create-zip-file-unix.html How would you best design this in terms of implementing concurrency controls in case "john" logs in and do a search/download and "mike" logs in and does another search/download.
Would you create one /tmp/ directory to dump all the files for all users and then ZIP all those order files into a unique zip filename? or would you use one directory per user /tmp/john/, /tmp/mike/ and clean up the directory each time they press the button. We only have one DB account. These are application user accounts stored in a table.
Can I also use the same zip file name or it has to be somehow unique.
Would you also call a direct link to the ZIP file bypassing mod_plsql so user can save the ZIP file to his PC? I think if i want to use mod_plsql I would need to upload this ZIP file from filesystem to a table first.
Can you advise on the best way to implement this.
Thanks,
September 21, 2011 - 9:31 am UTC
I probably would not create many files - but rather one file with an HTML list at the top that #linked to itself to get to each order. That way - just one file to deal with on the client (I'd be annoyed if you sent me X files - with possibly meaningless names - rather than a single file with links in it to see each order - where each link had a nice pretty descriptive name).
You would write that file out to the file system (you figure out the naming - I would probably incorporate a sequence in it) - the directory you write it to would either have to be a directory mapped in the webserver (so you can get files from there) or to a directory that is mapped inside the database as a DIRECTORY object - so you can BFILE the file and download it using mod_plsql. the latter would be more secure (if you put the zips into a mapped directory for the webserver, I could possibly guess file names and see other order files I should not be able to see)
then you can zip it - to the same name.zip or name.gz - which ever.
And then either redirect to the file using owa_util.redirect_url or file/download it using mod_plsql
OK
Daniel, October 07, 2011 - 6:18 am UTC
Hi Tom,
I was trying to create a java program in PL/SQL but I faced some issues which bewilder me.
Can you please take a look at it?
SQL> create or replace and compile java source named "Testjava"
2 as
3 import java.lang.*;
4 public class Testjava{
5 public static String ret_greet(String [] argcs){
6 return "Hello World";
7 };
8* }
SQL> /
Java created.
SQL> create or replace function f_java
2 return varchar2
3 as language java
4 name 'Testjava.ret_greet(java.lang.String)';
5 /
Warning: Function created with compilation errors.
SQL> show err
Errors for FUNCTION F_JAVA:
LINE/COL
--------------------------------------------------------------------------------
ERROR
--------------------------------------------------------------------------------
0/0
PL/SQL: Compilation unit analysis terminated
4/1
PLS-00311: the declaration of "Testjava.ret_greet(java.lang.String)" is incomple
te or malformed
October 07, 2011 - 1:56 pm UTC
you are creating a function, but you are not defining the return value.
search for:
function run_cmd
to see an example function stub for a java FUNCTION.
scp is not working through PL/SQL
Liviu, October 13, 2011 - 12:20 am UTC
Hi Tom,
I've read the previous discussions about starting external comands from pldql package. In my case I need to use scp to copy files between database hosts.
In my case, the java code is standard (see below) and it's working with any other host command except scp or ssh.
When I run scp command with oracle user in Bash, everithing works fine. (ssh is configured password less with key exchange). When I run from plsql I get return code 1 and nothing else.
Can you help me with an ideea.
Thanks,
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "joCmd" AS
import java.io.*;
import java.lang.*;
public class joCmd extends Object
{
public static int execute(String args, int wait , int verbose )
{
int status = -1;
Runtime rt = Runtime.getRuntime();
try
{
String line;
Process p = rt.exec(args);
BufferedReader input = new BufferedReader (new InputStreamReader(p.getInputStream()));
if(verbose==1)
{
while ((line = input.readLine()) != null) {
System.out.println(line);
}
}
if(wait==1)
status = p.waitFor();
else
status = 0;
input.close();
}
catch (Exception e)
{
e.printStackTrace();
return status;
}
finally
{
if(verbose==1)
System.out.println("Status:"+status);
return status;
}
}
}
October 13, 2011 - 7:31 am UTC
In your script that is running scp that you are calling from plsql, put in copious debug - capture all output (stdout and stderr) so you can see what it happening.
Error on running to command
Archana, February 17, 2012 - 12:12 am UTC
Hi Tom
Im on linux and 11g.
I get this error below on running ls -l command.
Error starting at line 1 in command:
begin rc('ls -l') ; end;
Error report:
ORA-00932: inconsistent datatypes: expected a Java type at argument position 2 to which some Oracle value can be converted got something else
I copied exactly same what you have mentioned for myuser.
Not sure if something needs to be changed
Geeting error when calling the plsql procedure
Leontin, October 19, 2012 - 9:26 am UTC
Hi Tom,
I followed your steps but I am getting this when running the plsql procedure. Please help.
Thanks,
Leontin
SQL> exec leontin_rc('/usr/bin/ps -ef');
BEGIN leontin_rc('/usr/bin/ps -ef'); END;
*
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected a Java type at argument position 2
to which some Oracle value can be converted got something else
October 23, 2012 - 11:25 am UTC
you changed something, and yet you don't show your work :(
sorry is all I can say therefore, I have no idea what you modified to break the working example.
Fixed ~ ORA-00932: inconsistent datatypes: expected a Java type at argument position 2
Shri Gupta, December 13, 2012 - 3:55 am UTC
Hello Tom,
I am working on 11g & Linux; copy pasted the exact code and got the below error
"ORA-00932: inconsistent datatypes: expected a Java type at argument position 2 to which some Oracle value can be converted got something else"
Modified the script as below
1. public static int RunThis(String[] args)
Changed to --> public static int RunThis(java.lang.String args)
2. Process p = rt.exec(args[0]);
Changed to --> Process p = rt.exec(args);
3. 'Util.RunThis(java.lang.String[])
Changed to --> 'Util.RunThis(java.lang.String)
Hope this helps.
Regards
Shri
SFTP shell script not working from PL/SQL
Bala, May 13, 2013 - 11:07 am UTC
Hi Tom,
I have used the code you have given to call the OS commands from PL/SQL. I made one shell script to transfer files from DB server to another server using FTP. I can be able to call that script from PL/SQL using "rc" procedure given by you. The same script I have modified to transfer the files using SFTP. Script is working well in Linux server, but the same script is not working when its called from PL/SQL. I am not able to understand the behaivour of this. Can you pls shed light on this problem.
May 13, 2013 - 1:13 pm UTC
you know that when it runs from plsql, it is running in an environment inherited ffrom the server process, it is running with the OS identity of the server process, in short - it is running in an entirely different environment from the one you are using at the command line.
start with debugging 101 techniques. In the script - dump out the id, uname and environment to a file in temp. Run the script with -vx or some other switches (debug mode) and redirect the output to that file in temp.
Now you'll have a file in temp that shows the environment you have, what identity you are running as and any errors encountered in the running of your script. this will be very illuminating - you won't even have to post that output, you'll be able to see what's going on straight off yourself.
Executing shell script
Vijay, May 13, 2013 - 5:16 pm UTC
Hi Tom,
I am trying to run a shell script using specified code.
Under SYS user :
=================
BEGIN
DBMS_JAVA.GRANT_PERMISSION ( 'RDM_OWNER', 'java.io.FilePermission', '/usr/bin/sh', 'execute' );
DBMS_JAVA.GRANT_PERMISSION ( 'RDM_OWNER', 'java.io.FilePermission', '/usr/bin/ps', 'execute' );
DBMS_JAVA.GRANT_PERMISSION ( 'RDM_OWNER', 'java.lang.RuntimePermission', '*', 'writeFileDescriptor' );
DBMS_JAVA.GRANT_PERMISSION ( 'RDM_OWNER', 'java.io.FilePermission', '/nas/aaa/devuser/*', 'execute' );
DBMS_JAVA.GRANT_PERMISSION ( 'RDM_OWNER', 'java.io.FilePermission', '/nas/aaa/devuser/script/*', 'execute' );
END;
/
PL/SQL procedure successfully completed.
I have one ksh file under path file /nas/aaa/devuser/script/helloworld.ksh
when i am trying execute that file getting return code 1 always.
created below procdure
--------------------------
create or replace
PROCEDURE RC(
p_cmd IN VARCHAR2)
AS
x NUMBER;
BEGIN
x := run_cmd(p_cmd);
dbms_output.put_line(x);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(sqlerrm);
END;
SQL> exec RC('/usr/bin/sh /nas/aaa/devuser/espresso/helloworld.ksh');
1
PL/SQL procedure successfully completed.
please suggest what more permission required. 'devuser' is a user mounted on same host where oracle installed.
Thanks
Vijay
May 13, 2013 - 5:28 pm UTC
oh - do not give access to /usr/bin/sh!!!!! that would let you run *anything*.
just run the script you want. (and why would you use sh to run a ksh???)
Executing shell script from oracle
Vijay, May 14, 2013 - 5:18 am UTC
Hi Tom ,
I Have given following permission as u suggested.
GRANT DEV_OWNER SYS java.io.FilePermission /nas/aaa/devuser/* execute ENABLED 118
GRANT DEV_OWNER SYS java.io.FilePermission /nas/aaa/devuser/script/* execute ENABLED 119
GRANT DEV_OWNER SYS java.io.FilePermission /nas/aaa/devuser/script/helloworld.ksh execute ENABLED 120
GRANT DEV_OWNER SYS java.io.FilePermission /usr/bin/ps execute ENABLED 115
GRANT DEV_OWNER SYS java.io.FilePermission /usr/bin/sh execute ENABLED 117
GRANT DEV_OWNER SYS java.lang.RuntimePermission * writeFileDescriptor ENABLED 116
-- And when i am trying to execute following getting error like below.
SQL> set serveroutput on size 1000000
SQL> exec dbms_java.set_output(1000000)
PL/SQL procedure successfully completed.
SQL> exec RC('/nas/aaa/devuser/script/helloworld.ksh');
java.io.IOException: /nas/aaa/devuser/script/helloworld.ksh not found
at java.lang.OracleProcess.create(Native Method)
at java.lang.OracleProcess.construct(OracleProcess.java:111)
at java.lang.OracleProcess.<init>(OracleProcess.java:41)
at java.lang.OracleProcess.start(OracleProcess.java:381)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:483)
at java.lang.Runtime.exec(Runtime.java:591)
at java.lang.Runtime.exec(Runtime.java:429)
at java.lang.Runtime.exec(Runtime.java:326)
at Util.RunThis(Util:14)
-1
PL/SQL procedure successfully completed.
-- "devuser" is a user mounted on same host where oracle installed.
-- "devuser" required password to switch into.Is this a reason my program is not able to reach that ksh.
please suggest how to reach ksh which is kept inside password enabled user ie. devuser in my example.
Thanks,
Vijay
<b></b><b></b>
May 14, 2013 - 12:29 pm UTC
you'll have to make it so the user that runs the dedicated server - what process id that process runs as - has read and execute on the directory and execute on the script. standard OS stuff.
it doesn't have to do with devuser needing a password, it has to do with the fact that the process owner the dedicated server is running under cannot 'see' that file.
Michael Kutz, May 14, 2013 - 1:50 pm UTC
If you are on 10g+, why not use DBMS_SCHEDULER instead?
May 14, 2013 - 5:12 pm UTC
that is an option maybe, however the same exact problems will exist as far as permissions and visibility go.
the issue with dbms_scheduler is that if you need to run this script from a procedure and then process the output - using the scheduler can really complicate your logic. If all you want to do is "run script, get output" and not "run this script on a recurring basis in the background" - the scheduler doesn't make it easy.
but yes, the scheduler can be used without having to install java code.
ZERO SIZE FILE OUTPUT
Mina, December 10, 2013 - 12:19 pm UTC
dear tom,
i have used this code to execute a .sh file that encrypts a file and places it in a folder, the code completes successfully but the output is one file with 0 size. When i run that script from UNIX it runs correctly and i have a usable output file.
can you please help me??
the used java code:
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED APPS."RuntimeDemo" AS
public class RuntimeDemo {
public static int shell() {
Runtime rt = Runtime.getRuntime();
int rc = -2;
try
{
Process p = rt.exec("sh /home/oracle/script_payment/newprogram.sh");
rc = p.waitFor();
return rc;
}
catch (Exception e)
{
e.printStackTrace();
System.err.println(e.getMessage());
rc = -1;
return rc;
}
}
}
create or replace
function APPS.XX_SHELL_EXECUTE return number
as
language java
name 'RuntimeDemo.shell() return integer';
declare
v_grantee constant varchar2(30) := 'APPS';
begin
dbms_java.grant_permission
(v_grantee,
'java.io.FilePermission',
'/usr/bin/sh',
'execute');
dbms_java.grant_permission
(v_grantee,
'java.lang.RuntimePermission',
'*',
'writeFileDescriptor' );
dbms_java.grant_permission
(v_grantee,
'java.lang.RuntimePermission',
'*',
'readFileDescriptor' );
end;
the used newprogram.sh file:
#!/bin/sh
echo 'Printing parameters....'
echo '1:'$1
echo 'Finished printing parameters.'
Filename=$1
echo $Filename
#DAY=`/bin/date +%d%m%Y`
#fileReferenceNumber=$(($2 + 1))
#DestinationFile=$1 #'HDF''1501'$DAY'.P00'$fileReferenceNumber
echo $DesinationFile
iconv -f utf-8 -t asmo-708 /oracledb/proddb/bank_files/$Filename > /oracledb/proddb/bank_files/out/$Filename
echo "Convert with iconv completed here"
echo $DesinationFile
#iconv -f text -t asmo-708 /oracledb/proddb/bank_files/$Filename > /home/oracle/script_payment/out/$DestinationFile
GPGFILE=$Filename'.gpg'
#gpg --recipient user@example.com --encrypt /home/oracle/out_anb/$DestinationFile
#echo $DestinationFile > /home/oracle/out/upload_file.txt
if test -f /oracledb/proddb/bank_files/out/$GPGFILE
then
echo 'File already exist.'
exit 0
fi
gpg --recipient user@example.com --encrypt /oracledb/proddb/bank_files/out/$Filename
#echo $Filename'.gpg' > /home/oracle/script_payment/out/upload_file.txt
echo $Filename'.gpg' > /oracledb/proddb/bank_files/out/upload_file.txt
/home/oracle/script_payment/uploadsftp1.sh
echo 'File uploaded SFTP Folder'
can be used to run host command on Linux server??
Fabrizio Delli Priscoli, January 02, 2014 - 2:27 pm UTC
Hi. I read this article and it was very interesting.
Can I use this example to run a host command on a Linux Server??
I explain my scenario: I have an oracle form application on server1 and I want to use code in this article to run a sql file that is on the same server (Linux) of the DB; this server is different from server1.
So what I want is to make possible from form application to write a command like this:
@/mydirectory/myfile.sql param1 param2
and so run myfile.sql that is located on linux server.
Hi followed all step, I have created all the code provided, but when I run the command
exec rc('@/mydirectory/myfile.sql');
I receive this error:
*
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected a Java type at argument position 2
to which some Oracle value can be converted got something else
So, where am I wrong??
Thanks for collaboration,
Fabrizio
Package java source
bakunian, June 05, 2014 - 7:17 pm UTC
Tom,
Is there a way to make Java source part of PL/SQL package body in 11gR2? Similar to following:
create or replace package body java_pkg as
JAVA SOURCE NAMED "WriteThis" AS
import java.io.FileWriter;
import java.io.IOException;
....
Thank you.
Dos2unix command
satish, September 04, 2014 - 7:50 am UTC
Hi Tom,
I need execute dos2unix command in remote unix machine from local system on some files which are in "/ftp/abc/def" path . so can you please give how do we need to call to RC function ?
running from the forms 11g
Srinivas, November 04, 2014 - 4:57 pm UTC
Hi tom,
We ahve a existing procedure to run the oscommand from forms 11g, using pl/sql procedure and java class.
declare
n number;
begin
n := Oscommand('cmd.exe /c E:\batch\file1.bat');
-
-
end;
this os command use the java class OSCommand.Run
my question is, where the command will execute, is it in db server or application server or in local.
we don't have any E:\batch\file1.bat path in local machine or in server. db server is unix server.
As per my knowledge the cmd.exe will call on db server, but db server is unix server.
Is there any way to set the machine name to run the os commands.
But and if I need a smbclient?
Vinicius Pacheco, November 01, 2019 - 6:41 pm UTC
Hi, Tom.
I've used your code to solve this situation: I need to send ZPLII files to a zebra printer from a dbms_scheduler job.
The database server is a Unix machine. It's a Oracle Database 11g Release 11.2.0.4.0 - 64bit Production
The printer is a network printer wich the print server is a Windows NT.
I gave the grants:
dbms_java.grant_permission ('WIS','java.io.FilePermission','/usr/bin/ps','execute');
dbms_java.grant_permission ('WIS','java.io.FilePermission','/usr/bin/ls','execute');
dbms_java.grant_permission ('WIS','java.io.FilePermission','/usr/bin/smbclient','execute');
dbms_java.grant_permission ('WIS','java.lang.RuntimePermission','*','writeFileDescriptor');
If I run your RC procedure to do a 'ps -ef' it works perfectly:
SQL> set define off
SQL> set lines 200
SQL> set serveroutput on size 1000000
SQL> exec dbms_java.set_output(1000000)
PL/SQL procedure successfully completed.
SQL> declare
2 cmd varchar2(2000);
3 begin
4 cmd := 'ls -la /home/oracle/oradata/zpl';
5 dbms_output.put_line(cmd);
6 rc(cmd);
7 end;
8 /
ls -la /home/oracle/oradata/zpl
total 72
drwxr-xr-x. 2 oracle oracle 45056 Oct 31 11:36 .
drwxr-xr-x. 7 oracle oracle 4096 Jul 25 10:40 ..
-rw-r--r-- 1 oracle oracle 1153 Oct 29 18:45 et.txt
-rw-r--r--. 1 oracle oracle 101 Oct 29 2014 e.txt
-rw-r--r--. 1 oracle oracle 18 Aug 28 13:47 nomeimpr.doc
-rw-r--r-- 1 oracle oracle 30 Aug 27 18:03 nomeimpr.doc.bk
-rw-r--r--. 1 oracle oracle 172 Dec 10 2010 proc-impr-etiq.sh
-rw-r--r-- 1 oracle oracle 1153 Aug 28 14:35 usada_para_testes.txt
X = 0
PL/SQL procedure successfully completed.
SQL>
But if I use it to call a smclient, it doesn't (the "xxxxxx" is only to hide actual users and paswords):
SQL> set define off
SQL> set lines 200
SQL> set serveroutput on size 1000000
SQL> exec dbms_java.set_output(1000000)
PL/SQL procedure successfully completed.
SQL> declare
2 cmd varchar2(2000);
3 begin
4 cmd := 'smbclient -U ''xxxxxx\xxxxxx%xxxxxx'' //serverps02/zebra_teste -c ''print /home/oracle/oradata/zpl/et.txt'' ';
5 dbms_output.put_line(cmd);
6 rc(cmd);
7 end;
8 /
smbclient -U 'xxxxxx\xxxxxx%xxxxxx' //serverps02/zebra_teste -c 'print /home/oracle/oradata/zpl/et.txt'
session setup failed: NT_STATUS_LOGON_FAILURE
X = 1
PL/SQL procedure successfully completed.
Of course, I've tested the smbclient command from bash to be sure it's correct:
smbclient -U 'xxxxxx\xxxxxx%xxxxxx' //serverps02/zebra_teste -c 'print /home/oracle/oradata/zpl/et.txt'
Domain=[xxxxxx] OS=[Windows Server 2012 Datacenter 9200] Server=[Windows Server 2012 Datacenter 6.2]
putting file /home/oracle/oradata/zpl/et.txt as et.txt-4931 (28.9 kb/s) (average 28.9 kb/s)
There is any aditional grant needed to run a smbclient instead a ps -ef?
Thanks a lot for all the knollege sharing on your site!
November 05, 2019 - 4:17 am UTC
Re: But and if I need a smbclient?
Vinicius Pacheco, November 06, 2019 - 6:07 pm UTC
Thanks a lot for your reply.
But I think I didn't understand your sugestion. Or you didn't understand my question. First one has bigger chances... :-)
From the links you posted and other reads, I understand that external tables are usefull to "import" to oracle some "outside" information...
But it is not what I'm trying to do. The information is already in the database. I just need to print some labels based on it, regardless a user take an action to this.
So there is a job that time to time seeks my tables for some condition. When it occurs, It's created a file (via utl_file) with the ZPLII commands. Untill here I got dthe code working.
But after creating the files, I need to send then to the printer. This is where I try to use java: just to do a print command that I can't do from the database.
I can't figure how to use external tables to print.
On the other hand, I didn't knew external tables and when I needed somethig like that I used to read files using utl_file. External tables seems more easy to do. So, thanks for the information, but, seems that isn't what I need.
November 07, 2019 - 3:13 am UTC
"But I think I didn't understand your sugestion".... that's still my fault - I need to explain better.
In (almost) any situation where you need to run a host command (any host command) from within the database, an external table can pretty much do that job now.
Obviously that is not what external tables were really designed for, but I find it a very easy and powerful mechanism to use because of the preprocessor option.
Let's say I needed to secure copy (scp) a file from a call *inside* the database. Then my preprocessor script could be something like:
/bin/scp $* remote_server:/tmp
echo DONE
The filename from the external table is passed into that preprocesor script and then you can do whatever you like with it.
So whilst it LOOKS like I did:
SQL> select output from my_external_table;
OUTPUT
--------
DONE
I have actually run the scp command due to the preprocessor script.
So you would put your smb calls (and anything you like) into your script, and then by *querying* the external table, you will run the host commands you desire.
Complilation errors for java source
Karim, January 29, 2020 - 4:24 pm UTC
HI Tom,
How can i fix the error of the function getTotalSpace() of the package
java.io.File showing that this function is not exist (im using oracle database 11g R2 , plsqldevelopr tool)
the error is :
Error: cannot find symbol
Text: s=d.getTotalSpace();
Example of procedure plsql :
create or replace and compile java source named "usbv" as
import java.io.File;
public class usbv {
public static String list_usbv () {
String n=null;
Long s;
File[] drives = File.listRoots();
if ((drives != null) &&(drives.length) > 0) {
for (File d : drives) {
if (d.canWrite()==true) {
try {
s=d.getTotalSpace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(s>0){
if (n==null)
n=""+d;
else
n=n+" "+d;
}
else
n=" ";
}
}
}
return n;
}
}
Thank you.
January 30, 2020 - 9:02 am UTC
See my previous review - I suggest moving to an external table or scheduler approach
add library java to oracle
karim, January 29, 2020 - 5:43 pm UTC
Hy Tom,
How can i add the library usb4java.jar to oracle database 11g.
Thank you.