Oracle 8i 無內建指令直接呼叫 OS 命令,但可透過 DBMS_PIPE 實現資料庫進程與外部守護進程通訊,達到在 SQL/預存程序中執行 OS 指令的目的。本文提供完整 DAEMON 套件實作碼。
daemon 管道 → 等待回覆。daemon 管道 → 執行 OS 指令 → 將結果寫入唯一回覆管道(DBMS_PIPE.UNIQUE_SESSION_NAME)。CREATE OR REPLACE PACKAGE BODY daemon AS
FUNCTION execute_system(command VARCHAR2, timeout NUMBER DEFAULT 10)
RETURN NUMBER IS
status NUMBER;
result VARCHAR2(20);
command_code NUMBER;
pipe_name VARCHAR2(30);
BEGIN
pipe_name := DBMS_PIPE.UNIQUE_SESSION_NAME;
DBMS_PIPE.PACK_MESSAGE('SYSTEM');
DBMS_PIPE.PACK_MESSAGE(pipe_name);
DBMS_PIPE.PACK_MESSAGE(command);
-- 發送指令至 daemon 管道
status := DBMS_PIPE.SEND_MESSAGE('daemon', timeout);
IF status <> 0 THEN
RAISE_APPLICATION_ERROR(-20010, 'Send error: ' || status);
END IF;
-- 接收執行結果
status := DBMS_PIPE.RECEIVE_MESSAGE(pipe_name, timeout);
IF status <> 0 THEN
RAISE_APPLICATION_ERROR(-20011, 'Receive error: ' || status);
END IF;
DBMS_PIPE.UNPACK_MESSAGE(result);
IF result <> 'done' THEN
RAISE_APPLICATION_ERROR(-20012, 'Done not received');
END IF;
DBMS_PIPE.UNPACK_MESSAGE(command_code);
DBMS_OUTPUT.PUT_LINE('System command executed. result=' || command_code);
RETURN command_code;
END execute_system;
PROCEDURE stop(timeout NUMBER DEFAULT 10) IS
status NUMBER;
BEGIN
DBMS_PIPE.PACK_MESSAGE('STOP');
status := DBMS_PIPE.SEND_MESSAGE('daemon', timeout);
IF status <> 0 THEN
RAISE_APPLICATION_ERROR(-20030, 'Stop send error: ' || status);
END IF;
END stop;
END daemon;
/
SHOW ERRORS;
RECEIVE_MESSAGE('daemon')。type、return_pipe、command。type='SYSTEM' 執行命令,將 'done' 與返回碼 PACK_MESSAGE 後 SEND_MESSAGE(return_pipe)。type='STOP' 則結束迴圈。-- 在 SQL*Plus 或預存程序中
BEGIN
daemon.execute_system('ls -l /tmp > /tmp/ls.out');
END;
/
-- 或查詢
SELECT daemon.execute_system('date') FROM dual;
EXECUTE ON daemon 權限,防止任意命令注入。oracle 軟體擁有者。DBMS_SCHEDULER 建立 EXECUTABLE 類型作業,原生支援 OS 指令執行,更安全便捷。