«

»

Выполнение ОС команд на сервере БД в sql, pl\sql коде.

Для выполнения команд операционной системы на сервере БД из sql (pl/sql) кода можно создать java класс, привязать к нему (классу) функцию или процедуру и уже ее вызывать из sql кода. В Internet много статей как это сделать (пример http://www.sql.ru/faq/faq_topic.aspx?fid=170), но на Solaris 10 с RDBMS Oracle 11.2.0.1 пользователь, под которым запущен сервер создает java процесс без каких либо переменных окружения. В итоге вызов комант завершается с ошибкой вида

ERROR>/usr/bin/kill[7]: basename: not found
ERROR>/usr/bin/kill[8]: -9: not found
ExitValue: 127

Проблема в том, что файл /usr/bin/kill не является просто исполняемым бинарным файлом, а представляет из себя код

#!/bin/ksh -p
#
#ident "@(#)alias.sh 1.2 00/02/15 SMI"
#
# Copyright (c) 1995 by Sun Microsystems, Inc.
#
cmd=`basename $0`
$cmd "$@"

Так как в процесс java не определены переменные окружения, то при выполнении скрипта не может быть найден файл basename.

Решение - вызывать метод  Runtime.getRuntime().exec() не с одним параметром командной стоки, но и передавать переменные окружения.

 

DROP JAVA SOURCE KDS."Util";

CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED KDS."Util" as import java.io.*;
import java.lang.*;

class StreamGobbler extends Thread
{
InputStream is;
String type;

StreamGobbler(InputStream is, String type)
{
this.is = is;
this.type = type;
}

public void run()
{
try
{
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line=null;
while ( (line = br.readLine()) != null)
System.out.println(type + ">" + line);
} catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
public class Util extends Object
{
public static int RunThis(String OsCmdLine, String[] CmdOutput)
{
int exitVal = -1;

if (OsCmdLine.length() < 1) {
System.out.println("USAGE: java Util.RunThis \'cmd\' OutputStringVariable");
System.exit(1);
}
try
{
//System.out.println("Running command: " + OsCmdLine);
String osName = System.getProperty("os.name" );
String[] envParams = new String [1];;
if( osName.equals( "Windows NT" ) )
{
envParams[0] = "Path=C:\\Windows\\system32;C:\\Windows";
}
else if( osName.equals( "SunOS" ) )
{
envParams[0] = "PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/ccs/bin:/usr/local/bin:usr/ccs/bin";
}
Process proc = Runtime.getRuntime().exec(OsCmdLine, envParams);
// any error message?
StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR");

// any output?
StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT");

// kick them off
errorGobbler.start();
outputGobbler.start();

// any error???
exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
}
catch (Exception e)
{
System.out.println("Error running command: " + OsCmdLine + "\n" + e.getMessage());
e.printStackTrace();
exitVal = -1;
}
finally
{
return exitVal;
}
}
}
/

CREATE OR REPLACE FUNCTION KDS.run_command_java (
fv_command IN VARCHAR2,
fv_output OUT VARCHAR2
)
RETURN NUMBER
AS
LANGUAGE JAVA
NAME 'Util.RunThis( java.lang.String,
java.lang.String[] ) return integer';
/

CREATE OR REPLACE PROCEDURE KDS.pr_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 pr_run_command_java;
/

И дать права на выполнение команд

exec dbms_java.grant_permission(user, 'SYS:java.io.FilePermission', 'C:\WINNT\system32\cmd.exe', 'execute' );
-- Можно сделать так, для всех файлов:
-- dbms_java.grant_permission(user, 'SYS:java.io.FilePermission', '<<ALL FILES>>', 'execute' )
--
exec dbms_java.grant_permission(user, 'SYS:java.lang.RuntimePermission', 'writeFileDescriptor', '' );
exec dbms_java.grant_permission(user, 'SYS:java.lang.RuntimePermission', 'readFileDescriptor', '' );

Permanent link to this article: http://www.blogss.ru/run_cmd_on_server

Добавить комментарий

Your email address will not be published.