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

本文介绍了如何在Oracle数据库中利用存储过程执行操作系统命令,包括使用Java存储过程和DBMS_PIPE程序包的方法。通过授予用户权限,创建Java类和函数,可以调用系统命令如ipconfig或执行bat文件。此外,还提到了一个名为DAEMON的Pro*C程序包,用于在服务器端接收并执行命令。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以下方法在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

... timePermission.html

... rityPermission.html

s/api/java/io/FilePermission.html

and

... 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    .

2004-05-15 15:47    ..

2002-12-24 20:13    archive

1998-09-09 18:31        31,744 oradba.exe

2004-05-08 11:48         568 OraDim.Log

2004-03-17 11:53        1,536 PWDweblish.ora

2004-05-15 15:47      1,871,872 SNCFWEBLISH.ORA

2003-12-29 13:24        2,560 SPFILEWEBLISH.ORA

2004-05-08 11:48        12,852 sqlnet.log

6 File(s)   1,921,132 bytes

3 Dir(s)  7,141,621,760 bytes free

-----------------

c:aa.bat如下:

cmd /c

dir

以下是利用proc实现:

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

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

下面介绍实现具体步骤:

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

/*创建daemon程序包*/CREATEORREPLACEPACKAGE BODY daemonAS/*execute_system是实现运行os命令的函数*/FUNCTIONexecute_system(commandVARCHAR2,

timeoutNUMBERDEFAULT10)RETURNNUMBERISstatusNUMBER;

resultVARCHAR2(20);

command_codeNUMBER;

pipe_nameVARCHAR2(30);BEGINpipe_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);IFstatus<>0THENRAISE_APPLICATION_ERROR(-20010,'Execute_system: Error while sending. Status ='||status);ENDIF;

status :=DBMS_PIPE.RECEIVE_MESSAGE(pipe_name, timeout);IFstatus<>0THENRAISE_APPLICATION_ERROR(-20011,'Execute_system: Error while receiving.

Status ='||status);ENDIF;/*获取返回结果*/DBMS_PIPE.UNPACK_MESSAGE(result);IFresult<>'done'THENRAISE_APPLICATION_ERROR(-20012,'Execute_system: Done not received.');ENDIF;

DBMS_PIPE.UNPACK_MESSAGE(command_code);

DBMS_OUTPUT.PUT_LINE('System command executed. result ='||command_code);RETURNcommand_code;ENDexecute_system;/*stop是让daemon停止*/PROCEDUREstop(timeoutNUMBERDEFAULT10)ISstatusNUMBER;BEGINDBMS_PIPE.PACK_MESSAGE('STOP');

status :=DBMS_PIPE.SEND_MESSAGE('daemon', timeout);IFstatus<>0THENRAISE_APPLICATION_ERROR(-20030,'stop: error while sending. status ='||status);ENDIF;ENDstop;ENDdaemon;

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

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

None.gif#include

None.gif#include

None.gifEXECSQL INCLUDE SQLCA;

None.gifEXECSQLBEGINDECLARESECTION;char*uid="scott/tiger";/*在这个地方改为你自己访问的用户,密码,服务名*/None.gifintstatus;

None.gifVARCHARcommand[20];

None.gifVARCHARvalue[2000];

None.gifVARCHARreturn_name[30];

None.gifEXECSQLENDDECLARESECTION;

None.gifvoid

None.gifconnect_error()

None.gif{

None.gifcharmsg_buffer[512];

None.gifintmsg_length;

None.gifintbuffer_size=512;

None.gifEXECSQL WHENEVER SQLERRORCONTINUE;

None.gifsqlglm(msg_buffer,&buffer_size,&msg_length);

None.gifprintf("Daemon errorwhileconnecting:n");

None.gifprintf("%.*sn", msg_length, msg_buffer);

None.gifprintf("Daemon quitting.n");

None.gifexit(1);

None.gif}

None.gifvoid

None.gifsql_error()

None.gif{

None.gifcharmsg_buffer[512];

None.gifintmsg_length;

None.gifintbuffer_size=512;

None.gifEXECSQL WHENEVER SQLERRORCONTINUE;

None.gifsqlglm(msg_buffer,&buffer_size,&msg_length);

None.gifprintf("Daemon errorwhileexecuting:n");

None.gifprintf("%.*sn", msg_length, msg_buffer);

None.gifprintf("Daemon continuing.n");

None.gif}

None.gifmain()

None.gif{

None.gifEXECSQL WHENEVER SQLERROR DO connect_error();

None.gifEXECSQL CONNECT :uid;

None.gifprintf("Daemon connected.n");

None.gifEXECSQL WHENEVER SQLERROR DO sql_error();

None.gifprintf("Daemon waiting...n");

None.gifwhile(1) {

None.gifEXECSQLEXECUTENone.gifBEGIN/*接收deamon发来的字符*/None.gif:status :=DBMS_PIPE.RECEIVE_MESSAGE('daemon');

None.gifIF:status=0THEN/*取出字符*/None.gifDBMS_PIPE.UNPACK_MESSAGE(:command);

None.gifENDIF;

None.gifEND;

None.gifEND-EXEC;

None.gifIF(status==0)

None.gif{

None.gifcommand.arr[command.len]='';/*如果是stop,该进程就退出*/None.gifIF(!strcmp((char*) command.arr, "STOP"))

None.gif{

None.gifprintf("Daemon exiting.n");

None.gifbreak;

None.gif}

None.gifELSEIF(!strcmp((char*) command.arr, "SYSTEM"))

None.gif{

None.gifEXECSQLEXECUTENone.gifBEGINNone.gifDBMS_PIPE.UNPACK_MESSAGE(:return_name);

None.gifDBMS_PIPE.UNPACK_MESSAGE(:value);

None.gifEND;

None.gifEND-EXEC;

None.gifvalue.arr[value.len]='';

None.gifprintf("Willexecutesystem command'%s'n", value.arr);/*运行os命令*/None.gifstatus=system(value.arr);

None.gifEXECSQLEXECUTENone.gifBEGINNone.gifDBMS_PIPE.PACK_MESSAGE('done');

None.gifDBMS_PIPE.PACK_MESSAGE(:status);

None.gif:status :=DBMS_PIPE.SEND_MESSAGE(:return_name);

None.gifEND;

None.gifEND-EXEC;

None.gifIF(status)

None.gif{

None.gifprintf

None.gif("Daemon errorwhilerespondingtosystem command.");

None.gifprintf(" status:%dn", status);

None.gif}

None.gif}

None.gifELSENone.gif{

None.gifprintf

None.gif("Daemon error: invalid command'%s'received.n",

None.gifcommand.arr);

None.gif}

None.gif}

None.gifELSENone.gif{

None.gifprintf("Daemon errorwhilewaitingforsignal.");

None.gifprintf(" status=%dn", status);

None.gif}

None.gif}

None.gifEXECSQLCOMMITWORKRELEASE;

None.gifexit(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.gifSQL>variable rvnumberNone.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的文档.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值