16. Januar 2008

Download verfügbar: Betriebssystem Kommandos aus der Datenbank ausführen

Download available: Executing OS commands from the database

Bereits vor einiger Zeit habe ich einen Post mit etwas Code zum Ausführen von Betriebssystem-Kommandos aus der Datenbank heraus veröffentlicht. Diesen Code habe ich nun mit dem Code zum Anzeigen von Verzeichnisinhalten zusammengeführt und zum Download bereitgestellt. Die erste Version 0.2 ist bei weitem noch nicht vollständig - aber es wird weitere Versionen geben.
Feedback, damit das Paket immer besser wird, ist natürlich erwünscht ...
Some time ago I posted some code for executing operating system commands from the database - now I merged this code with another post about retrieving directory contents with SQL and made it available as a download. This first version (0.2) is not complete (of course) but there will be additions in the future.
I appreciate feedback - so that the package gets better and better ...

Kommentare:

daust_de hat gesagt…

Hallo Carsten,

gute Idee.

Ich würde es gut finden, wenn noch ein paar mehr Beispiele vorhanden wären, wie man es genau einsetzt.

Der Java Ansatz funktioniert ja bereits seit 8i, vielleicht kannst Du hier noch ein paar Anregungen finden:
http://www.oracle-base.com/articles/8i/ShellCommandsFromPLSQL.php
http://www.oracle-base.com/articles/8i/FileHandlingFromPLSQL.php

Insbesondere die Klasse für das Filehandling ist dort ziemlich elegant gemacht, und es gibt auch einen strukturierten Zugriff auf die Verzeichnisinhalte. Wenn man die Liste im Array hat, kann man jeweils noch die weiteren File-Attribute ermitteln.

Leider läuft diese Fassung nicht auf Oracle XE, das muß man über den DBMS_SCHEDULER machen (oder andere DLLs über external procedure calls einbinden).

Viele Grüße,
~Dietmar.

Carsten Czarski hat gesagt…

Hi Dietmar,

danke für das Feedback die Links - die kannte ich noch nicht. Mehr Anwendungsbeispiele wird es mit der nächsten Version geben; dort werde ich auch noch PL/SQL-Prozeduren hinzufügen, die den OS Return Code zurückgeben.

Was (so wie ich das sehe) bislang noch nicht da war, ist die Integration mit STDIN bzw. STDOUT; so kann man bspw. aufrufen ...

$ echo TEXT TEXT > text.txt
$ gzip text.txt

SQL> select os_command.exec_clob('gunzip -c /home/oracle/text.txt.gz') from dual;

OS_COMMAND.EXEC_CLOB('GUNZIP-C/HOME/ORACLE/TEXT.TXT.GZ')
--------------------------------------------------------------------------------
TEXT TEXT

1 Zeile wurde ausgewählt.

Die Prozedur GET_FILE_LIST möchte ich ohnehin noch um die File-Attribute erweitern - interessant ist hier, dass sie als TABLE FUNCTION vorliegt, also die Dateiliste nicht einfach nur als String zurückgibt.

... mehr dazu, wenn die Homepage fertig ist ... stay tuned ...

Viele Grüße

-Carsten

Carsten Czarski hat gesagt…

... oder komplett ohne Datei ...

SQL> select os_command.exec_blob('gzip -c', 'Hallo Welt') from dual;

OS_COMMAND.EXEC_BLOB('GZIP-C','HALLOWELT')
--------------------------------------------------------------------------------
1F8B08008B0C8F470003F348CCC9C957084FCD290100751428500A000000

1 row selected.

Elapsed: 00:00:00.44

... der zweite Parameter wird an STDIN übergeben; STDOUT wird zurückgegeben ...

daust_de hat gesagt…

Hallo Carsten,

ja, die Integration mit stdin/out und das Beispiel mit dem GZIP gefällt mir sehr gut.

Wenn Du das integrierst mit den Sachen von Tim Hall (oracle-base) sollte das eine richtig runde Sache werden.

Ich finde den Ansatz von Tim's API sehr gut. Das Dir-Listing liefert Dir nur eine Liste von Dateinamen (oder Verzeichnissen). Die können dann weiter untersucht werden, oder sogar die Verzeichnisse rekursiv durchlaufen werden.

Jeder kann dann mit weiteren Zugriffen der API genau die Details holen, die er benötigt. Somit ist die API auch einfacher zu erweitern und existierender Code bleibt stabil.

Oder Du übergibst beim Aufruf des Directory Listings Parameter, welche Attribute zurückgeliefert werden sollen und welche Filter angewendet werden sollen (z.B. nur Verzeichnisse, nur Dateien, beides).

Oder man macht es wie manchmal in Java, daß man selbst einen Filter als Code übergeben kann ;).

Viele Grüße,
~Dietmar.

chzi hat gesagt…

Hallo,
das Tool ist super.

Allerdings habe ich das Problem, das ich eine Taskliste von Windows einlesen möchte (z.B. select os_command.exec_clob('cmd.exe /c c:\hp\tool\ps -ef') from dual; oder select os_command.exec_clob('cmd.exe /c tasklist') from dual;

Ich bekomme leider in den CLOB nicht die Liste sondern der CLOB ist einfach leer.

Mache ich etwas falsch?

PS: Und ich kann nicht wirklich java

Danke für die Hilfe

Carsten Czarski hat gesagt…

Hallo,

funktioniert denn ein ...

select os_command.exec_clob('cmd.exe /c dir') from dual;

???

das Ganze ist Java-basierend; und gerade auf Windows-Plattformen gibt es bei manchen Kommandos Probleme mit der Übernahme der Ausgabe; das hängt davon ab, wie das Kommando mit STDIN, STDOUT und STDERR umgeht ...

Viele Grüße

-Carsten

chzi hat gesagt…

Hallo Carsten,
ein select os_command.exec_clob('cmd.exe /c dir') from dual; funktioniert !!!! :-)

Ich benötige ein Tool mit dem ich prüfen kann, ob ein OS Prozess vorhanden ist oder nicht (z.B. Prozess EXCEL)

Haben Sie noch andere Ideen?

Danke

Carsten Czarski hat gesagt…

Hallo,

anscheinend macht die Prozeßliste auf Windows Probleme ... hmm ... das einzige, was ich mir noch vorstellen kann, wäre eine Skriptdatei / Batchdatei, die prüft, ob der Prozeß da ist und dann 1 oder 0 zurückgibt; dann müsste man die Prozeßliste nicht in die DB übernehmen ...

Vielleicht guck' ich mal, ob ich im nächsten Release was machen kann ... aber versprechen kann ich nix ...

-Carsten

tensai hat gesagt…

Hallo Carsten,

ich hab mir das FILE_PKG-Package im Schema SYS installiert, beide GRANT-Scripte ausgeführt, und wollte nun einfach mal das tmp-Verzeichnis ausgeben lassen..

Bekam dabei aber leider 'nen ORA 6553 ("wrong number or types of arguments in call to 'GET_FILE_LIST'").

So sieht das SQL-Statement aus: select * from table(file_pkg.get_file_list('/tmp'));
, es handelt sich um ne 10gR2-Datenbank auf einer Linux-Maschine.

Ich vermute mal, dass ich irgend ne Kleinigkeit übersehen habe - aber ich komm einfach nicht drauf :(

Würde mich über Hilfe freuen,
Daniel

Carsten Czarski hat gesagt…

Hallo Daniel,

ist nur eine Kleinigkeit:

select * from table(file_pkg.get_file_list(file_pkg.get_file('/tmp')));

GET_FILE_LIST nimmt keinen String, sondern wiederum einen FILE_TYPE entgegen; und den holt man sich mit FILE_PKG.GET_FILE

Beste Grüße

-Carsten

tensai hat gesagt…

Hallo Carsten,

Danke für die schnelle Antwort - das war ja wirklich nur ne Kleinigkeit ;)

Grüße,
Daniel

Beliebte Postings