Oracle DB. Выполнение команды на уровне ОС из СУБД посредством Java.

Иногда бывают такие ситуации, когда у нас есть доступ к СУБД, но нет доступа к операционной системе. А он нужен вот прям позарез, перенести какие-нибудь файлы или посмотреть структуру каталогов, например.
В такой ситуации на помощь может прийти хранимая процедура на Java.


В этой статье все действия выполняются от имени пользователя SYS. Если хотите повторить действия из под другого пользователя необходимо добавить ему разрешения:
begin
dbms_java.grant_permission(‘MYUSER’, ‘SYS:java.lang.RuntimePermission’, ‘writeFileDescriptor’, »);
dbms_java.grant_permission(‘MYUSER’, ‘SYS:java.lang.RuntimePermission’, ‘readFileDescriptor’, »);
dbms_java.grant_permission(‘MYUSER’, ‘SYS:java.io.FilePermission’, ‘/bin/sh’, ‘execute’);
end;


Для начала необходимо скомпилировать основной класс на Java:

create or replace and compile java source named host as
import java.io.*;
public class Host {
  public static String executeCommand(String command) {
    String buff = null;
    String tmp ="";
    try {
      String[] finalCommand;
      if (System.getProperty("os.name").toLowerCase().indexOf("windows") != -1) {
        finalCommand = new String[4];
        finalCommand[0] = "C:\\winnt\\system32\\cmd.exe";
        finalCommand[1] = "/y";
        finalCommand[2] = "/c";
        finalCommand[3] = command;
      } else {                                                // Linux or Unix System
        finalCommand = new String[3];
        finalCommand[0] = "/bin/sh";
        //finalCommand[0] = "";
        finalCommand[1] = "-c";
        finalCommand[2] = command;
      }

      // Execute the command...
      final Process pr = Runtime.getRuntime().exec(finalCommand);
      
      // Capture output from STDOUT...
      BufferedReader br_in = null;
      try {
        br_in = new BufferedReader(new InputStreamReader(pr.getInputStream()));
        tmp =tmp+"STDOUT: "+"\n";
        while ((buff = br_in.readLine()) != null) {
          //System.out.println("stdout: " + buff);
          tmp=tmp+buff+"\n";
          try {Thread.sleep(100); } catch(Exception e) {}
        }
        br_in.close();
      } catch (IOException ioe) {
        //System.out.println("Error printing process output.");
        tmp =tmp+ "Error printing process output."+"\n";
        //ioe.printStackTrace();
      } finally {
        try {
          br_in.close();
        } catch (Exception ex) {}
      }
      
      // Capture output from STDERR...
      BufferedReader br_err = null;
      try {
        br_err = new BufferedReader(new InputStreamReader(pr.getErrorStream()));
        tmp =tmp+"\n"+"STDERR: "+"\n";
        while ((buff = br_err.readLine()) != null) {
          //System.out.println("stderr: " + buff);
          tmp=tmp+buff+"\n";
          try {Thread.sleep(100); } catch(Exception e) {}
        }
        br_err.close();
        return tmp;
      } catch (IOException ioe) {
        //System.out.println("Error printing execution errors.");
        tmp =tmp+ "Error printing execution errors."+"\n";
        //ioe.printStackTrace();
      } finally {
        try {
          br_err.close();
        } catch (Exception ex) {}
      }
    }
    catch (Exception ex) {
      tmp =tmp+ ex.getLocalizedMessage()+"\n";
    }
    return tmp;
  }

};

После этого необходимо развернуть обертку к нему на PL/SQL:

create or replace function host (p_command IN VARCHAR2) return varchar2
   AS LANGUAGE JAVA
   NAME 'Host.executeCommand (java.lang.String) return String';

После чего можно приступать к выполнению команд на уровне ОС, например ls:

begin
  dbms_output.put_line(host('/bin/ls /opt'));
end;

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *