oracle的java存储过程执行系统命令

这两天折腾着做了个用oracle的java存储过程执行系统命令的功能,在网上找了很多资料,总算解决了,整理出来,顺便复习一下

[b][color=red]需求[/color][/b]是: 在数据库中有个job定时执行某任务,其中需要调用操作系统命令生成多个文件夹和文件内容,并把他们打包.
[b][color=red]环境[/color][/b]是: linux AS3 ,oracle 9.2.0.4
[b][color=red]实现过程[/color][/b]:
1、 用sysdba用户赋予执行job的数据库用户权限,包括文件操作的权限和执行系统命令的权限,命令为:
SQL> exec dbms_java.grant_permission('USERNAME','SYS:java.io.FilePermission','<<ALL FILE>>','read,write,execute,delete');
SQL> exec dbms_java.grant_permission('USERNAME','SYS:java.lang.RuntimePermission','*','WriteFileDescriptor');
其中,USERNAME是数据库用户名,<<ALL FILE>>指所有文件
2、用执行job的用户登录,并编写java存储过程
[color=red]java代码[/color]
public class RunCmd
{
public static int Run(String args)
{
Runtime rt = Runtime.getRuntime();
String os=System.getProperty("os.name").toLowerCase().trim();

String cmd[]={"/bin/sh","-c",args};
int rc = -1;
try{
if(rt!=null&&args!=null){
Process p;
if(os.startsWith("windows")) //windows环境下
p = rt.exec(args);
else
p=rt.exec(cmd); //linux环境下,暂时不考虑其他环境
if(p!=null){
int bufSize = 4096;
BufferedInputStream bis =new BufferedInputStream(p.getInputStream(), bufSize);
int len;
byte buffer[] = new byte[bufSize];
while ((len = bis.read(buffer, 0, bufSize)) != -1)
System.out.write(buffer, 0, len);
rc = p.waitFor();
}else{
System.out.println("p is null");
}
}else{
System.out.println("rt/args is null");
}
}catch (Exception e)
{
e.printStackTrace();
rc = -1;
}
finally
{
System.out.println("rc="+rc);
return rc;
}
}
}
其中,要注意的是在windows环境和linux环境对命令执行的不同,是因为linux下有重定向的问题。

[color=red]oracle函数定义[/color]
create or replace function RUN_CMD(p_cmd in varchar2) return Number
As
language Java name 'RunCmd.Run(java.lang.String) return integer';

[color=red]主任务过程[/color]
create or replace procedure tartask(pdtask in number,path in varchar2) Is
Cursor cur_code Is
Select code,title From pd_res Where task_id=pdtask;
v_code Varchar2(10);
v_rc Number;
v_file Varchar2(400);
v_cmd Varchar2(4000);
v_str Varchar2(4000);
v_title Varchar2(500);
Begin
--在linux环境下
--创建任务主目录
v_cmd:='mkdir '||path||'/'||pdtask;
v_rc:=run_cmd(v_cmd);

--对每个资源,创建子目录
Open cur_code;
Loop
Begin
Fetch cur_code Into v_code,v_title;
Exit When cur_code%Notfound;
--code
v_cmd:= 'mkdir '||path||'/'||pdtask||'/'||v_code;
v_rc:=run_cmd(v_cmd);
--meta
--mkdir meta
v_cmd:= 'mkdir '||path||'/'||pdtask||'/'||v_code||'/meta';
v_rc:=run_cmd(v_cmd);
v_file:=path||'/'||pdtask||'/'||v_code||'/meta/dc.xml';
-----------------------------------------------------------------------------------------
--dc.xml
--echo 123321 > d:\1.txt
-- v_cmd:='export LANG=utf-8';
-- v_rc:=run_cmd(v_cmd);

v_str:='<?xml version=\"1.0\" encoding=\"utf-8\"?>';
v_cmd:=' echo -E "'||v_str||'" > '||v_file;
v_rc:=run_cmd(v_cmd);
v_cmd:='echo -E "" >> '||v_file;
v_rc:=run_cmd(v_cmd);

v_str:='<dublincore xmlns:dc=\"http://purl.org/dc/elements/1.0/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:dcterms=\"http://purl.org/dc/terms/\">';
v_cmd:= 'echo -E "'||v_str||'" >> '||v_file;
v_rc:=run_cmd(v_cmd);
v_cmd:='echo -E "" >> '||v_file;
v_rc:=run_cmd(v_cmd);

v_str:='<dc:identifier>'||v_code||'</dc:identifier>';
v_cmd:= 'echo -E "'||v_str||'" >> '||v_file;
v_rc:=run_cmd(v_cmd);
v_cmd:='echo -E "" >> '||v_file;
v_rc:=run_cmd(v_cmd);

-- v_str:='<dc:title>'||'中国 泰山'||'</dc:title>';
--v_cmd:= 'echo -E "'||v_str||'" >> '||v_file;
-- v_rc:=run_cmd(v_cmd);
-- v_cmd:='echo -E "" >> '||v_file;
-- v_rc:=run_cmd(v_cmd);

v_str:='</dublincore>';
v_cmd:= 'echo -E "'||v_str||'" >> '||v_file;
v_rc:=run_cmd(v_cmd);
v_cmd:='echo -E "" >> '||v_file;
v_rc:=run_cmd(v_cmd);
End;
End Loop;
Close cur_code;

--打包创建好的目录
v_cmd:='tar -zcvf '||path||'/'||pdtask||'.tar.gz'||' '||path||'/'||pdtask;
v_rc:=run_cmd(v_cmd);
end tartask;
这是在linux环境下的任务代码,windows环境下类似,就是输入的命令稍微有些不同,其中包括了目录创建,文件创建和写文件,注掉部分是因为中文问题解决不了,输入的中文都存成乱码,最后决定这个由人工来录入;

[b][color=red]问题和总结[/color][/b]
在这次解决过程中,遇到了几个问题
1、windows下和linux下调用系统命令的输入,windows下,命令形式为:cmd /c dir,整个是一个字符串输入,而在linux下,需要用{"/bin/sh","-c","ls"}这样的数组形式输入
2、创建并写文件,用echo xxx > filepath 命令
3、在用echo写文件的过程中,遇到了“>”符不能输入的问题,因为会被误认为是重定向符号>,在windows里,可以用在>前加^符号来解决,在linux下,用命令echo带参数 -E 解决
4、在用echo写文件时,换行,写入新行,在windows下,用 echo. > filepath,就是在echo后直接跟一个.号解决,在linux下,用 echo "" > filepath解决
5、echo的>是创建并写入,因此如果该文件存在,会被覆盖,如果需要在文件末添加数据,用>>代替>
6、就是中文的问题,目前还没有解决掉,把java类放到操作系统里执行写中文是没有问题的,echo进去没问题,但是放到oracle里写就会是乱码,不知道是什么地方需要设置,实在是把我折腾坏了,先放着,以后或许忽然就看到解决方法了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值