技术开发 频道

在pl/sql中调用shell命令

    【IT168 技术文档】本来想是一个很简单的操作,可惜Oracle没有提供简单的一个命令(也许我不知道吧),只好进行一些复杂点的操作了。一般有三种方式实现:

    1. 利用DBMS_PIPE包并创建OS上运行的守护进程;

    2. 利用java的getRuntime().exec;

    3. 使用oracle的EXECUTABLE jobs功能。

    利用DBMS_PIPE包并创建OS上运行的守护进程

    觉得这种方式复杂,还要用到pro*c,没试。

    利用java的getRuntime().exec

    这种好点,java用的还是蛮多的。

    1)写个简单的java程序 ExecuteCmd.java

import java.lang.Runtime; import java.lang.Process; import java.io.IOException; import java.lang.InterruptedException; class ExecuteCmd { public static void main(String args[]) { System.out.println("Start executing"); try { /* Execute the command using the Runtime object and get the Process which controls this command */ Process p = Runtime.getRuntime().exec(args[0]); /* Use the following code to wait for the process to finish and check the return code from the process */ try { p.waitFor(); /* Handle exceptions for waitFor() */ } catch (InterruptedException intexc) { System.out.println("Interrupted Exception on waitFor: " + intexc.getMessage()); } System.out.println("Return code from process: "+ p.exitValue()); System.out.println("Done executing"); /* Handle the exceptions for exec() */ } catch (IOException e) { System.out.println("IO Exception from exec: " + e.getMessage()); e.printStackTrace(); } } }

    2)编译生成 ExecuteCmd.class

    javac ExecuteCmd.java

    3)加载到oracle中

    $ loadjava -user system/manager ExecuteCmd.class

    4)生成java存储过程

CREATE OR REPLACE PROCEDURE executecmd (S1 VARCHAR2) AS LANGUAGE JAVA name 'ExecuteCmd.main(java.lang.String[])'; /

    测试:

SQL> set serveroutput on SQL> call dbms_java.set_output(2000); SQL> EXEC executecmd('/bin/touch /home/oracle/a.txt'); Start executing Return code from process: 0 Done executing PL/SQL procedure successfully completed. SQL> host $ ls /home/oracle a.txt

    执行成功了,但还是有些问题,比如参数中不能使用环境变量 EXEC executecmd('/bin/touch $HOME/a.txt')执行不行,绝对路径和相对路径的问题,还要给执行用户(这里是system用户)授予相应的权限等等。所以我觉得还是应该先把要做的事写一个shell可执行脚本,然后再如上调用,这样会省去一些麻烦。

    使用oracle的EXECUTABLE jobs功能

    对DBMS_SCHEDULER没什么研究,论坛上有个例子,但我没试通,有时间再研究一下,应该也可以。

exec DBMS_SCHEDULER.CREATE_JOB (job_name=>'test13',job_type=>'EXECUTABLE',job_action=>'/tmp/test1.sh'); exec DBMS_SCHEDULER.RUN_JOB(job_name=>'test13');
0
相关文章