14. Mai 2007

Betriebssystem-Kommandos aus der Datenbank starten

Ab und zu kommt die Anforderung auf, ein Betriebssystem-Kommando aus der Datenbank heraus aufzurufen. Wenn man mal danach sucht (via Oracle MetaLink oder Google), dann finden sich dazu auch recht viele Tipps und Möglichkeiten. Manchmal wird empfohlen, das Paket DBMS_SCHEDULER einzusetzen, an anderer Stelle findet sich der Hinweis, man solle sich ein kleines C-Programm schreiben, kompilieren und dann mit CREATE LIBRARY einbinden und und und ...
Hier findet Ihr nun die dritte, ganz bequeme Variante. Der Aufruf des Betriebssystem-Kommandos wird mit Java in der Datenbank gemacht - das ist aber bereits vorhanden und erfordert keine separate Software. Als kleines Extra erlaubt die Java-Variante auch das Auslesen der Standardausgabe bzw. das Schreiben von Daten in die Standardeingabe - wendet man es richtig an, so kann man auf dem Betriebssystem eine Pipe mit mehreren Kommandos erzeugen, Daten nach STDIN schreiben und die Ergebnisse aus STDOUT herausholen ...
Eine Warnung vorab: Das Ausführen von Betriebssystem-Kommandos durch "normale" Datenbankuser ist ein Sicherheitsrisiko, da alle Kommandos mit den Rechten des Oracle-Systemusers ausgeführt werden. Weiter unten seht Ihr, dass der DBA dazu auch passende Rechte vergeben muss. Diese Rechte sollten so restriktiv wie möglich vergeben werden. Insbesondere wenn Benutzereingaben aus einer Anwendung in die Aufrufe eingebaut werden sollen, ist höchste Vorsicht geboten !!!
Doch genug der Vorrede: Hier der Code (Download)
Nochmal: Betriebssystem-Aufrufe sind ein Sicherheitsrisiko. Wie oben bereits erwähnt, darf in der Oracle-Datenbank nicht jeder Datenbankuser einfach Betriebssystem-Kommandos ausführen. Der DBA muss vorher Rechte einräumen werden. Dies geht mit folgendem Skript:
declare
  v_grantee constant varchar2(30) := 'SCOTT';
begin
  dbms_java.grant_permission(
    grantee =>           v_grantee,
    permission_type =>   'SYS:java.lang.RuntimePermission',
    permission_name =>   'readFileDescriptor',
    permission_action => null
  );
  dbms_java.grant_permission(
    grantee =>           v_grantee,
    permission_type =>   'SYS:java.lang.RuntimePermission',
    permission_name =>   'writeFileDescriptor',
    permission_action => null
  );
  -- gibt ALLE Kommandos frei: Sehr unsicher
  /*
  dbms_java.grant_permission( 
    grantee =>           v_grantee, 
    permission_type =>   'SYS:java.io.FilePermission', 
    permission_name =>   '<<ALL FILES>>', 
    permission_action => 'execute' 
  );
  */
  -- erlaubt nur die Ausführung des "ls"-Kommandos
  dbms_java.grant_permission(
    grantee =>           v_grantee,
    permission_type =>   'SYS:java.io.FilePermission',
    permission_name =>   '/bin/ls',
    permission_action => 'execute'
  );
end;
/
sho err

Achtung: Der auskommentierte Teil des Skripts mit << ALL FILES >> gibt sehr weitreichende Privilegien - Der Datenbankuser könnte damit alle Betriebssystem-Kommandos ausführen. Dies sollte in der Praxis eigentlich nie verwendet werden!. Anstelle dessen lieber (wie auch hier) die Befehle einzeln freigeben - oder ein Shell-Skript schreiben und nur das Skript freigeben.
Ist alles vorbereitet, kann das neue PL/SQL-Paket OS_COMMAND verwendet werden:
select os_command.exec_clob('ls -la /') from dual

OS_COMMAND.EXEC_CLOB('LS-LA/')
---------------------------------------------------------------------

insgesamt 203
drwxr-xr-x   22 root   root        512 2007-04-17 01:33 .
drwxr-xr-x   22 root   root        512 2007-04-17 01:33 ..
drwxr-xr-x    2 root   root       2920 2006-12-13 15:42 bin
drwxr-xr-x    3 root   root        464 2005-07-19 14:20 boot
drwxr-xr-x   33 root   root     180056 2007-05-22 09:18 dev
drwxr-xr-x   66 root   root       6400 2007-05-22 09:18 etc
drwxr-xr-x    3 root   root         72 2005-07-19 14:23 home
drwxr-xr-x   12 root   root       3256 2005-07-19 14:06 lib
drwxr-xr-x    4 root   root         96 2004-10-04 17:24 media
drwxr-xr-x    3 root   root         72 2006-12-13 13:25 mnt
:

Keine Kommentare:

Beliebte Postings