Oracle 8i 並無內建直接執行作業系統命令的 SQL 指令。雖可透過 Oracle Enterprise Manager (OEM) 排程作業達成,但 OEM 參數固定、缺乏彈性。本文介紹利用 DBMS_PIPE 管道機制,建立資料庫與外部 Daemon 進程雙向通訊,實現動態執行 OS 命令。
DAEMON,提供 EXECUTE_SYSTEM(command, timeout) 函數,負責封裝指令、發送至 daemon 管道、等待並解封裝回傳結果。daemon 管道,接收指令、執行 system()、將結果寫入唯一回應管道。PACK_MESSAGE → SEND_MESSAGE('daemon') → Daemon 接收 → 執行 → PACK_MESSAGE → SEND_MESSAGE(unique_pipe) → DB 接收結果。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);
status := DBMS_PIPE.SEND_MESSAGE('daemon', timeout);
IF status <> 0 THEN
RAISE_APPLICATION_ERROR(-20010, 'Execute_system: Error while sending. Status=' || status);
END IF;
status := DBMS_PIPE.RECEIVE_MESSAGE(pipe_name, timeout);
IF status <> 0 THEN
RAISE_APPLICATION_ERROR(-20011, 'Execute_system: Error while receiving. Status=' || status);
END IF;
DBMS_PIPE.UNPACK_MESSAGE(result);
IF result <> 'done' THEN
RAISE_APPLICATION_ERROR(-20012, 'Execute_system: Command failed. Result=' || result);
END IF;
RETURN 0;
END;
END daemon;
/
DBMS_PIPE.UNIQUE_SESSION_NAME:產生唯一管道名稱,避免多會話衝突。PACK_MESSAGE / SEND_MESSAGE:將多項資料序列化發送至指定管道。RECEIVE_MESSAGE / UNPACK_MESSAGE:阻塞等待並解析回應資料。timeout 參數:防止無限期阻塞,建議設定合理秒數。下一篇將提供完整的 C 語言 Daemon 端程式碼,示範如何編譯部署、處理命令執行與錯誤回傳,完成端到端實作。