Oracle 8i 缺乏直接在 SQL/PL/SQL 中執行作業系統命令的指令。雖可透過 Oracle Enterprise Manager (OEM) 排程作業,但參數固定、缺乏彈性。利用 DBMS_PIPE 套件建立命名管道,可讓資料庫會話與外部 Pro*C 守護進程雙向通訊,實現動態執行 OS 命令。
DAEMON,提供 EXECUTE_SYSTEM 函數發送命令、接收回傳碼;STOP 程序終止守護進程。daemon 管道,接收命令、執行、將結果寫回專屬回覆管道。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, '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('Command executed, code=' || command_code);
RETURN command_code;
END;
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;
END daemon;
#include
#include
EXEC SQL INCLUDE SQLCA;
EXEC SQL BEGIN DECLARE SECTION;
char *uid = "scott/tiger@orcl"; // 依實際環境修改
int status;
VARCHAR command;
VARCHAR value[2000];
VARCHAR return_name[30];
EXEC SQL END DECLARE SECTION;
void connect_error() {
char msg[512];
int len = 512;
sqlglm(msg, &len, &len);
fprintf(stderr, "Connection error: %s\n", msg);
exit(1);
}
int main() {
EXEC SQL CONNECT :uid;
if (sqlca.sqlcode != 0) connect_error();
while (1) {
// 1. 接收 daemon 管道訊息
// 2. 解析命令類型 (SYSTEM/STOP)
// 3. 若 SYSTEM:執行 OS 命令 (system() 或 popen())
// 4. 將結果 (done, return_code) 寫回 return_name 管道
// 5. 若 STOP:中斷迴圈清理資源
}
return 0;
}
proc iname=daemon.pc),再編譯連結生成執行檔。DBMS_PIPE.UNIQUE_SESSION_NAME 確保會話隔離,避免多用戶並發衝突。DBMS_SCHEDULER、DBMS_JAVA、UTL_FILE 等替代方案時的權宜之計。DBMS_SCHEDULER 外部作業、Java Stored Procedure 或 ORACLE_SCHEDULER_AGENT,更安全且標準化。