Meine Anforderung besteht darin, einen Systembefehl wie (ls) oder C-Programm auszuführen, wenn ein Trigger ausgeführt wird. Gibt es eine Möglichkeit, eine Triggerfunktion zu erstellen, um dieses Problem zu lösen?
Meine Anforderung besteht darin, einen Systembefehl wie (ls) oder C-Programm auszuführen, wenn ein Trigger ausgeführt wird. Gibt es eine Möglichkeit, eine Triggerfunktion zu erstellen, um dieses Problem zu lösen?
Antworten:
Sie können leicht tun, was @a_horse_with_no_name in seinem Kommentar vorschlägt. Es gibt aber auch eine interessante Möglichkeit, PL / pgSQL als Funktionssprache zu verwenden.
Dies verwendet eine Funktion des COPY
Befehls, der in PostgreSQL 9.3 eingeführt wurde. Es kann jetzt einen Befehl als Ziel / Quelle annehmen, genau dort, wo Sie im Normalfall einen Dateinamen oder STDIN / STDOUT verwenden würden:
COPY table_name [ ( column_name [, ...] ) ] FROM { 'filename' | PROGRAM 'command' | STDIN } [ [ WITH ] ( option [, ...] ) ]
Natürlich benötigen Sie eine Tabelle, um die Ausgabe zu platzieren, aber Sie können sie ignorieren, wenn Sie möchten.
Sehen Sie sich ein kleines Beispiel an:
CREATE TABLE trigger_test (
tt_id serial PRIMARY KEY,
command_output text
);
CREATE OR REPLACE FUNCTION trigger_test_execute_command()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $BODY$
BEGIN
COPY trigger_test (command_output) FROM PROGRAM 'echo 123';
RETURN NULL;
END;
$BODY$;
CREATE TABLE trigger_test_source (
s_id integer PRIMARY KEY
);
CREATE TRIGGER tr_trigger_test_execute_command
AFTER INSERT
ON trigger_test_source
FOR EACH STATEMENT
EXECUTE PROCEDURE trigger_test_execute_command();
INSERT INTO trigger_test_source VALUES (2);
TABLE trigger_test;
tt_id │ command_output
───────┼────────────────
1 │ 123
Hinweis: Die Funktion muss mit Superuser-Rechten ausgeführt werden, dh entweder INSERT
als Superuser ausführen oder die Funktion mit definieren SECURITY DEFINER
. In jedem anderen Fall erhalten Sie eine Fehlermeldung:
ERROR: must be superuser to COPY to or from an external program
HINT: Anyone can COPY to stdout or from stdin. psql's \copy command also works for anyone.
TO PROGRAM
Teil ein Zeichenfolgenliteral erforderlich ist. Wenn Sie also einen dynamischen Befehl wünschen, müssen Sie das Ganze einschließen EXECUTE
. Siehe stackoverflow.com/a/42626659/5419599 .
Wenn Sie sich nur etwas Relatives ansehen müssen, können $PGDATA
Sie pg_ls_data verwenden
SELECT pg_ls_dir('pg_xlog');
Ansonsten eine einfache Funktion wie diese:
CREATE OR REPLACE FUNCTION ls(location text) RETURNS text AS $BODY$
use warnings;
use strict;
my $location = $_[0];
my $output = `ls -l $location`;
return($output);
$BODY$ LANGUAGE plperlu;
Gibt Ihnen folgende Ausgabe:
user1@[local]:5432:user1:=# SELECT * FROM ls('/usr/local/pgsql/data');
ls
-----------------------------------------------------------------------------------------
total 104 +
-rw------- 1 pgsql pgsql 4 Jan 14 14:33 PG_VERSION +
drwx------ 8 pgsql pgsql 8 Jan 15 12:27 base +
drwx------ 2 pgsql pgsql 54 Feb 4 01:30 global +
drwx------ 2 pgsql pgsql 4 Jan 15 12:57 pg_clog +
drwx------ 2 pgsql pgsql 2 Jan 14 14:33 pg_commit_ts +
drwx------ 2 pgsql pgsql 2 Jan 14 14:33 pg_dynshmem +
-rw------- 1 pgsql pgsql 4458 Feb 4 01:29 pg_hba.conf +
-rw------- 1 pgsql pgsql 1725 Jan 20 15:29 pg_ident.conf +
drwx------ 4 pgsql pgsql 5 Feb 4 02:14 pg_logical +
drwx------ 4 pgsql pgsql 4 Jan 14 14:33 pg_multixact +
drwx------ 2 pgsql pgsql 3 Feb 4 01:29 pg_notify +
drwx------ 2 pgsql pgsql 2 Jan 14 14:33 pg_replslot +
drwx------ 2 pgsql pgsql 2 Jan 14 14:33 pg_serial +
drwx------ 2 pgsql pgsql 2 Jan 14 14:33 pg_snapshots +
drwx------ 2 pgsql pgsql 2 Feb 4 01:29 pg_stat +
drwx------ 2 pgsql pgsql 8 Feb 4 02:17 pg_stat_tmp +
drwx------ 2 pgsql pgsql 3 Jan 15 13:08 pg_subtrans +
drwx------ 2 pgsql pgsql 2 Jan 14 14:33 pg_tblspc +
drwx------ 2 pgsql pgsql 2 Jan 14 14:33 pg_twophase +
lrwxr-xr-x 1 pgsql pgsql 29 Jan 14 14:34 pg_xlog -> /usr/local/pgsql/xlog/pg_xlog+
-rw------- 1 pgsql pgsql 88 Jan 14 14:33 postgresql.auto.conf +
-rw------- 1 pgsql pgsql 21821 Jan 20 15:27 postgresql.conf +
-rw------- 1 pgsql pgsql 53 Feb 4 01:29 postmaster.opts +
-rw------- 1 pgsql pgsql 79 Feb 4 01:29 postmaster.pid +
(1 row)
Time: 4.361 ms
user1@[local]:5432:user1:=#
SECURITY DEFINER
) ausgeführt werden kann.