Ausführen eines externen Programmes

Hallo,

ich habe bereits im Internet (und auch in diesem Forum) gesucht, aber keine klare Antwort auf meine Frage gefunden.

Wie kann ich in PostgreSQL z.B. aus einer Stored Procedure oder aus einem Trigger heraus eine externe Exe öffnen, z.B. C:\windows\system32\notepad.exe?

Ich hoffe ihr könnt mir helfen :slight_smile:

Mit freundlichen Grüßen

nur mit untrusted languages, also stored procs, die in einer untrusted language geschrieben sind. Im allgemeinen will man das auch nicht. Warum willst Du das?

Sobald sich eine bestimmte Spalte in einer Tabelle öffnet, soll ein Programm gestartet werden, das Informationen aus einer Datei ließt und diese in die Datenbank schreibt. Die Argumente werden dabei dem Exe-Programm von der Datenbank übergeben.

Haben Sie vielleicht ein kleines Beispiel für so einen Aufruf?
Welche Untrusted Sprache sind zu empfehlen?

Was bitte meinst Du damit?

Spalten einer Tabelle “öffnen” sich nicht einfach so. Entweder selektiert man deren Werte über ein SQL Statement, oder ändert diese über ein UPDATE statement, oder fügt neue Datensätze über INSERT hinzu. Aber “geöffnet” werden Spalten nie.

Eigentlich keine, weil eben ‘untrusted’ :wink:. Ich hatte auch noch nie die Notwendigkeit z.B. Python auf DB-Ebene einzusetzen. Das mag im Einzelfall aber anders sein.
Wenn du nach einem Update oder Insert noch etwas machen willst bietest sich ein Trigger an. Aber warum willst du da ein externes Programm starten? Ich würde das Einlesen von Daten eher als Aufgabe einer Middleware ausserhalb der Datenbank sehen. Aber genaues können wir dir nur raten, wenn wir wissen was du denn tun willst.

Gruß Uwe

DataMaster hat geschrieben:
Sobald sich eine bestimmte Spalte in einer Tabelle öffnet

Oh, entschuldigung. Als ich das geschrieben habe, was ich gedanklich wohl nicht ganz bei der Sache :slight_smile:

Ich meinte:
Sobald in einer Tabelle eine Zeile hinzugefügt wird.

Das habe ich mit einem Insert-Trigger realisiert. Nun muss nur noch ein externes Programm gestartet werden.

Die größeren Zusammenhänge sind leider schwer zu erklären. Die Datenbank bekommt halt mit, wenn ein neuer Eintrag hinzugefügt wird, und darauf hin soll ein externes Programm gestartet werden, das darauf hin Dateien ausliest und wiederum selber in die gleiche Datenbank Werte schreibt.

Ich habe leider noch nich viel Erfahrung mit Postgres. Ich habe bisher mit SQL-Server gearbeitet.
Ich sehe aber, dass man in Postgres beim Anlegen einer neuen Funktion zwischen 3 Sprachen wählen kann:

  • plgpsql
  • internal
  • C.

Ist C untrusted? Und was ist internal?

es gibt noch etliche mehr, pl/perl, pl/perlU, pl/tcl, pl/tclU, pl/lolcode, pl/v8, pl/sh, … die mit dem U im Namen - das U steht für untrusted. C auch.

Du solltest Deinen Plan überdenken. Erstell lieber eine Tabelle, die die auszuführenden Dinge enthält. Mit einem externen Programm (CRON unter *NIX als Beispiel) rufst dann zyklisch ein externes programm auf, welches diese Tabelle ausliest und abarbeitet.

So wie Du das planst baust Dir jede Menge Probleme ein. Was, wenn das externe Programm nicht fertig wird? Was, wenn es fehlerhaft arbeitet? Das ist in einem TRIGGER alles sehr unschön.

Tja, wenn was schief geht, habe ich Pech :slight_smile:

Im Prinzip will ich nur eine Funktion, die bekommt als Argument einen vollen Pfad zu einem Programm.

Und dieses toll ausgeführt werden. Es ist dabei egal, ob der Code in pl/perlU oder pl/pythonU realisiert ist. :sunglasses:

Ich werde mal das untrusted Python für Postgres anschauen. Damit müsste es gehen.
Nur blöd, dass man extra “untrusted”-Sprachen installieren muss. :rolleyes:

das ‘untrusted’ bezieht sich eben exakt auf diese Eigenschaft, Dinge zu tun, die aus Sicht der DB unsicher sind. Dazu gehört eben insbesondere der Zugriff auf das Filesystem, unter anderem, um externe Programme aufzurufen und damit (aus Sicht der DB) die Kontrolle aus der Hand zu geben.

Kann mir jemand bei der Installation der Programme helfen?

ich kann weder pl/python, noch pl/perl installieren.

Wenn ich in PG Admin III

CREATE EXTENSION plperlu;

eingebe, bekomme ich folgende Meldung:

FEHLER:  konnte Bibliothek „C:/Program Files/PostgreSQL/9.3/lib/plperl.dll“ nicht laden: unknown error 126
********** Fehler **********

FEHLER: konnte Bibliothek „C:/Program Files/PostgreSQL/9.3/lib/plperl.dll“ nicht laden: unknown error 126
SQL Status:58P01

Unter “C:\Program Files\PostgreSQL\9.3\lib” befindet sich aber die Datei “plperl”.

Das gleiche passiert, wenn ich

CREATE EXTENSION plpython3u;



FEHLER:  konnte Bibliothek „C:/Program Files/PostgreSQL/9.3/lib/plpython3.dll“ nicht laden: unknown error 126
********** Fehler **********

FEHLER: konnte Bibliothek „C:/Program Files/PostgreSQL/9.3/lib/plpython3.dll“ nicht laden: unknown error 126
SQL Status:58P01

Muss ich bei der Installation etwas beachten? Ich habe im Internet nur gefunden, dass es so funktionieren müsste. :frowning:

Das Problem bei untrusted ist, das die externen Dinge mit den Rechten des Datenbankdienstes laufen. Je nach dem kann man dann deine Datenbank zerstören, das ist also eine große Sicherheitslücke. Wie auch immer, in deinem Fall würde ich die Ausführung in eine Middleware auslagern und deren Ergebnis dann in die DB schreiben. Den auszuführenden Pfad hast du ja eh schon oder du holst ihn dir halt aus der DB. Einen anderen Weg hast du ja auch schon wie das sicher abzuwickeln geht.
Wie auch immer, vermutlich brauchst du für plpythonu einen externen Python-Interpreter, hast du den installiert?

Gruß Uwe

Ja, ich habe Python installiert.
Das interessante ist, dass ich garkeine Extension installieren kann.
Weder pl/perl, pl/pyhton noch pl/tcl.

Mit dem Programm “Dependency Walker” sehe ich, dass DLL-Dateien fehlen…
Bei pl/tclu fehlt z.B.
“Postgres.EXE” und “TCL85.DLL”.

Ich benutze Windows 7 und Postgres 9.3.5.

Kann es sein, dass da einfach paar DLL-Dateien nicht mitgeliefert wurden?

Da gibt es doch die Funktion Copy in pl/pgsql.

Interessant erscheint mir da der ‘PROGRAM’-Parameter.

Kann man vielleicht damit etwas machen?

Das ist aus der Doku:

To copy into a compressed file, you can pipe the output through an external compression program:

COPY country TO PROGRAM ‘gzip > /usr1/proj/bray/sql/country_data.gz’;

>

Ja, du brauchst aber Superuser-Rechte in der DB dazu.

Jup, die Superrechte habe ich.

Ich habe zuerst dies getestet:

COPY hm_messages TO PROGRAM 'I:\Test\notepad.exe';

Dann wird Notepad.exe gestartet, allerdings unter dem Benutzer “NETZWERKDIENST”.
Außerdem bleibt die Stored Procedure an dem Aufruf stehen, als ob sie solange wartet, bis irgendetwas erfolgreich abgeschlossen ist.

Erst wenn ich den Prozess über den Task-Manager beende, wird das Warten abgebrochen.

Der Server gibt dann folgende Ausgabe:

FEHLER:  Programm „I:\Test\notepad.exe“ fehlgeschlagen
DETAIL:  Kindprozess hat mit Code 1 beendet
CONTEXT:  SQL-Anweisung „COPY hm_messages TO PROGRAM 'I:\Test\notepad.exe'“
PL/pgSQL-Funktion testx() Zeile 7 bei SQL-Anweisung
********** Fehler **********

Wie kann ich der Stored Procedure sagen, dass beim COPY-Befehl nicht warten soll, sondern einfach weiterlaufen?

Außerdem will ich das Programm nicht als Nutzer “Netzwerkdienst” starten, sondern als Nutzer “alle” (so ist sein Name :slight_smile: )

Programme kann man mit “runas” mit einem anderen Benutzer starten, allerdings startet er dann NotePad überhaupt nicht.

COPY hm_messages TO PROGRAM 'runas.exe /user:alle /savecred "I:\Test\notepad.exe"';

Folgender Fehler wird ausgegeben:

FEHLER:  Programm „runas.exe /user:alle /savecred "I:\Test\notepad.exe"“ fehlgeschlagen
DETAIL:  Kindprozess hat mit Code 1 beendet
CONTEXT:  SQL-Anweisung „COPY hm_messages TO PROGRAM 'runas.exe /user:alle /savecred "I:\Test\notepad.exe"'“
PL/pgSQL-Funktion testx() Zeile 6 bei SQL-Anweisung
********** Fehler **********

Wenn ich aber ‘runas.exe /user:alle /savecred “I:\Test\notepad.exe”’ direkt in die Kommandozeile eingebe, funktioniert es.

Ich hoffe, ihr könnt mir helfen.


Nachtrag:

So, habe Pyhton für Postgres installiert bekommen. Ichbenutze Postgres 9.3.5. Dafür muss für Python eine speziele Version installiert werden.
3.4, die ich zuvor intalliert hatte, geht nicht.

http://www.python.org/ftp/python/3.2/python-3.2.amd64.msi

Die Lösung habe ich von dort:

Habe nun mit pl/python3u folgendes zusammengebaut:

CREATE OR REPLACE FUNCTION runApplication()
  RETURNS void AS
$BODY$
	import subprocess
	subprocess.call("runas.exe /user:alle /savecred \"I:\Test\notepad.exe\"")

	RETURN
$BODY$
  LANGUAGE plpython3u VOLATILE
  COST 100;
ALTER FUNCTION runApplication()
  OWNER TO postgres;

Allerdings bleiben meine Probleme bestehen:

  1. Das Program wird mit dem Nutzer “Netzwerkdienst” gestartet,
  2. Die Stored Procedure wartet so lange, bis das Programm beendet wurde.

Ich hätte das Programm schon gerne mit dem Nutzer “alle” gestartet.
Und die Stored Procedure sollte das Programm nur anstoßen und dann weiterlaufen.

Habt ihr Ideen?

Ja, wir haben Ideen. Und die nannten wir Dir schon.

Hallo,

das mit dem “Warten” habe ich so gelöst, dass ich aus der Python-Stored Procedure nicht direkt die exe starte, sondern eine Bat-Datei, die dann die Exe startet.

Wichtig ist aber, dass die exe in der bat-Datei mit “start” gestartet wird.

Code der Bat:

start I:\Test\Notepad.exe

Bei einfachem “I:\Test\Notepad.exe” (ohne start) würde die Stored Procedure warten.