利用oracle存储过程执行操作系统命令(转)

以下方法在WINNT,LINUX下的oracle9i上测试通过,java过程调用系统命令
  
  首先给使用java存储过程的用户授予一定的权限
  <>表示所有文件,也可以单独指定文件。
  r w e d表示四种操作
  
  
   Code:
  Dbms_Java.Grant_Permission('HR',
  'java.io.FilePermission', '<>',
  'read ,write, execute, delete');
  
  Dbms_Java.Grant_Permission('HR',
  'java.io.FilePermission', 'd:aa.bat',
  'read ,write, execute, delete');
  
   dbms_java.grant_permission
    ('HR',
    'java.lang.RuntimePermission',
    '*',
    'writeFileDescriptor' );
   end;
   /
  PL/SQL procedure successfully completed.
  
  See
  
  http://java.sun.com/j2se/1.3/doc ... timePermission.html
  
  http://java.sun.com/j2se/1.3/doc ... rityPermission.html
  
  http://java.sun.com/j2se/1.3/docs/api/java/io/FilePermission.html
  
  and
  
  http://download-east.oracle.com/ ... 53/perf.htm#1001971
  From the “Java Developer’s Guide”, Part No. A81353-01, Chapter 5:
  
  Table 5?1 Permission Types
  n java.util.PropertyPermission
  n java.io.SerializablePermission
  n java.io.FilePermission
  n java.net.NetPermission
  n java.net.SocketPermission
  n java.lang.RuntimePermission
  n java.lang.reflect.ReflectPermission
  n java.security.SecurityPermission
  n oracle.aurora.rdbms.security.PolicyTablePermission
  n oracle.aurora.security.JServerPermission
  
  相关的java类如下
  SQL> connect hr/hr@ts
  已连接。
  
  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;
     }
     }
    }
   /
  
  Java created.
  
  建立函数
  
  create or replace
  function RUN_CMD(p_cmd in varchar2) return number
    as
   language java
    name 'Util.RunThis(java.lang.String) return integer';
  /
  
  Function created.
  
  建立一过程调用函数
   create or replace procedure RC(p_cmd in varchar2)
   as
    x number;
   begin
    x := run_cmd(p_cmd);
   end;
   /
  
  Procedure created.
  
  SQL> variable x number;
  SQL> set serveroutput on
  SQL> exec dbms_java.set_output(100000);
  
  PL/SQL procedure successfully completed.
  
  可以执行相应的命令和bat文件
  SQL> exec :x := RUN_CMD('ipconfig');
  
  Windows 2000 IP Configuration
  
  Ethernet adapter 本地连接
  :
  
      Connection-specific DNS Suffix . :
      IP Address. . . . . . . . . . . . : 172.18.25.102
      Subnet Mask . . . . . . .
  . . . . : 255.255.255.0
      Default Gateway . . . . . . . . . : 172.18.25.1
  
  PL/SQL 过程已成功完成。
  
  也可以执行服务器上的bat文件
  SQL>  exec :x := RUN_CMD('c:aa.bat');
  c:oracleora92DATABASE>cmd /c
  c:oracleora92DATABASE>dir
  Volume in drive C is 本地磁盘
  Volume Serial Number is 5CE1-2622
  Directory of c:oracleora92DATABASE
  2004-05-15 15:47   

以下是利用proc实现:

在Oracle 8i中,往往会出现要在存储过程中运行操作系统命令的情况.一般来说,利用Oracle Enterprise Manager设定作业时可以达到这个目的.但是由于OEM在设定作业缺乏灵活性,设定的作业的参数是固定的.在实际应用当中往往需要在SQL语句当中运行需要随时运行操作系统命令.Oracle 8i没有直接运行OS命令的语句,我们可以利用DBMS_PIPE程序包实现这一要求.

DBMS_PIPE通过创建管道,可以让至少两个进程进行通信.Oracle的管道与操作系统的管道在概念上有相同的地方,但是在实现机制不同.
下面介绍实现具体步骤:

1 创建一个程序包,姑且起名叫DAEMON,SQL语句如下:

 
  
/*创建daemon程序包*/ CREATE OR REPLACE PACKAGE BODY daemon AS /*execute_system是实现运行os命令的函数*/ FUNCTION execute_system(command VARCHAR2 , timeout NUMBER DEFAULT 10 ) RETURN NUMBER IS status NUMBER ; result VARCHAR2 ( 20 ); command_code NUMBER ; pipe_name VARCHAR2 ( 30 ); BEGIN pipe_name : = DBMS_PIPE.UNIQUE_SESSION_NAME; DBMS_PIPE.PACK_MESSAGE( ' SYSTEM ' ); DBMS_PIPE.PACK_MESSAGE(pipe_name); None.gif DBMS_PIPE.PACK_MESSAGE(command); /*向daemon管道发送表示命令的字符*/ status : = DBMS_PIPE.SEND_MESSAGE( ' daemon ' , timeout); IF status <> 0 THEN RAISE_APPLICATION_ERROR( - 20010 , ' Execute_system: Error while sending. Status = ' || status); END IF ; status : = DBMS_PIPE.RECEIVE_MESSAGE(pipe_name, timeout); IF status <> 0 THEN RAISE_APPLICATION_ERROR( - 20011 , ' Execute_system: Error while receiving. Status = ' || status); END IF ; /*获取返回结果*/ DBMS_PIPE.UNPACK_MESSAGE(result); IF result <> ' done ' THEN RAISE_APPLICATION_ERROR( - 20012 , ' Execute_system: Done not received. ' ); END IF ; DBMS_PIPE.UNPACK_MESSAGE(command_code); DBMS_OUTPUT.PUT_LINE( ' System command executed. result = ' || command_code); RETURN command_code; END execute_system; /*stop是让daemon停止*/ PROCEDURE stop(timeout NUMBER DEFAULT 10 ) IS status NUMBER ; BEGIN DBMS_PIPE.PACK_MESSAGE( ' STOP ' ); status : = DBMS_PIPE.SEND_MESSAGE( ' daemon ' , timeout); IF status <> 0 THEN RAISE_APPLICATION_ERROR( - 20030 , ' stop: error while sending. status = ' || status); END IF ; END stop; END daemon;

通过Sql*Plus运行以上语句,将为当前用户创建daemon程序包.

2 创建在OS上运行的守护进程,监听由上面的daemon程序包发来的要求执行os命令的语句.以下Pro*C的代码,必须由pro*c先进行预编译.

 
  
None.gif #include None.gif#include None.gif EXEC SQL INCLUDE SQLCA; None.gif EXEC SQL BEGIN DECLARE SECTION; char * uid = "scott / tiger"; /*在这个地方改为你自己访问的用户,密码,服务名*/ None.gif int status; None.gif VARCHAR command [ 20 ] ; None.gif VARCHAR value [ 2000 ] ; None.gif VARCHAR return_name [ 30 ] ; None.gif EXEC SQL END DECLARE SECTION; None.gifvoid None.gifconnect_error() None.gif{ None.gif char msg_buffer [ 512 ] ; None.gif int msg_length; None.gif int buffer_size = 512 ; None.gif EXEC SQL WHENEVER SQLERROR CONTINUE ; None.gifsqlglm(msg_buffer, & buffer_size, & msg_length); None.gifprintf("Daemon error while connecting:n"); None.gifprintf(" % . * sn", msg_length, msg_buffer); None.gifprintf("Daemon quitting.n"); None.gif exit ( 1 ); None.gif} None.gifvoid None.gifsql_error() None.gif{ None.gif char msg_buffer [ 512 ] ; None.gif int msg_length; None.gif int buffer_size = 512 ; None.gif EXEC SQL WHENEVER SQLERROR CONTINUE ; None.gifsqlglm(msg_buffer, & buffer_size, & msg_length); None.gifprintf("Daemon error while executing:n"); None.gifprintf(" % . * sn", msg_length, msg_buffer); None.gifprintf("Daemon continuing.n"); None.gif} None.gifmain() None.gif{ None.gif EXEC SQL WHENEVER SQLERROR DO connect_error(); None.gif EXEC SQL CONNECT :uid; None.gifprintf("Daemon connected.n"); None.gif EXEC SQL WHENEVER SQLERROR DO sql_error(); None.gifprintf("Daemon waiting...n"); None.gif while ( 1 ) { None.gif EXEC SQL EXECUTE None.gif BEGIN /*接收deamon发来的字符*/ None.gif:status : = DBMS_PIPE.RECEIVE_MESSAGE( ' daemon ' ); None.gif IF :status = 0 THEN /*取出字符*/ None.gifDBMS_PIPE.UNPACK_MESSAGE(:command); None.gif END IF ; None.gif END ; None.gif END - EXEC ; None.gif IF (status == 0 ) None.gif{ None.gifcommand.arr [ command.len ] = ' ' ; /*如果是stop,该进程就退出*/ None.gif IF (!strcmp(( char * ) command.arr, "STOP")) None.gif{ None.gifprintf("Daemon exiting.n"); None.gif break ; None.gif} None.gif ELSE IF (!strcmp(( char * ) command.arr, "SYSTEM")) None.gif{ None.gif EXEC SQL EXECUTE None.gif BEGIN None.gifDBMS_PIPE.UNPACK_MESSAGE(:return_name); None.gifDBMS_PIPE.UNPACK_MESSAGE(:value); None.gif END ; None.gif END - EXEC ; None.gifvalue.arr [ value.len ] = ' ' ; None.gifprintf("Will execute system command ' %s ' n", value.arr); /*运行os命令*/ None.gifstatus = system(value.arr); None.gif EXEC SQL EXECUTE None.gif BEGIN None.gifDBMS_PIPE.PACK_MESSAGE( ' done ' ); None.gifDBMS_PIPE.PACK_MESSAGE(:status); None.gif:status : = DBMS_PIPE.SEND_MESSAGE(:return_name); None.gif END ; None.gif END - EXEC ; None.gif IF (status) None.gif{ None.gifprintf None.gif("Daemon error while responding to system command."); None.gifprintf(" status: % dn", status); None.gif} None.gif} None.gif ELSE None.gif{ None.gifprintf None.gif("Daemon error: invalid command ' %s ' received.n", None.gifcommand.arr); None.gif} None.gif} None.gif ELSE None.gif{ None.gifprintf("Daemon error while waiting for signal."); None.gifprintf(" status = % dn", status); None.gif} None.gif} None.gif EXEC SQL COMMIT WORK RELEASE; None.gif exit ( 0 ); None.gif}

以上代码起名为daemon.pc,用proc预编译:

proc iname=daemon.pc userid=用户名/密码@服务名 sqlcheck=semantics

得到daemon.c,在用c进行编译,注意在NT上要把orasql8.lib加上,否则编译通过,连接没法通过.

3 在服务器上运行daemon.exe

4 在sqlplus运行测试语句:

 
  
None.gif SQL > variable rv number None.gifSQL > execute :rv : = DAEMON.EXECUTE_SYSTEM( ' ls -la ' ); None.gifPL / SQL 过程已成功完成。 None.gifSQL > execute :rv : = DAEMON.EXECUTE_SYSTEM( ' dir ' ); None.gifPL / SQL 过程已成功完成。

DBMS_PIPE的用法见oracle的文档.

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/756652/viewspace-242204/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/756652/viewspace-242204/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值