【AIO】使用ORACLE存储过程执行windows操作系统命令

从oracle 10g版本起,添加了schedule job功能,该功能支持调用操作系统命令
image.png
所以我们可以做个这样的尝试,
将要执行的操作系统命令通过utl_file包生成一个.bat文件,然后通过schedule job来执行这个bat文件,
举个例子,如果我们想要定时重启windows上的时间时间同步服务,在cmd下是执行

net stop w32time
net start w32time

那么我们可以把这两条命令,写成一个time_r.bat文件,

 V_File := Utl_File.Fopen(I_db_Path,I_file_name ,'W');
 Utl_File.Put_Line(V_File, l_cmd_text);
 Utl_File.Fclose(V_File);

保存在D:\TEMP\time_r.bat,然后创建一个不自动执行的临时schedule job,

begin
  sys.dbms_scheduler.create_job(job_name            => 'SYS.TIME_R',
                                job_type            => 'EXECUTABLE',
                                job_action          => 'c:\windows\system32\cmd.exe /c "time_r.bat"',
                                start_date          => to_date('02-07-2017 00:00:00', 'dd-mm-yyyy hh24:mi:ss'),
                                repeat_interval     => 'Freq=Hourly;Interval=4;ByMinute=50;BySecond=0',
                                end_date            => to_date(null),
                                job_class           => 'DEFAULT_JOB_CLASS',
                                enabled             => false,
                                auto_drop           => false');
end;
/

再执行这个scheduler JOB,

begin
dbms_scheduler.run_job('SYS.TIME_R');
end;

执行完后删除这个job和bat文件(删job也可通过“auto_drop”参数控制,但不方便调试排查故障)。

 UTL_FILE.FREMOVE(I_db_Path, I_file_name );
 dbms_scheduler.drop_job(I_job_name);

为了方便灵活使用,我们可以把中间步骤全部进行抽象,封装成一个存储过程,实际使用时无需去管job和bat文件。比如下面这个样子

declare
l_cmd_text VARCHAR2(4000);
begin
l_cmd_text:='net stop w32time
net start w32time';
TEXT_TO_CMD_P(l_cmd_text);
end;

但是实际使用中可能会遇到几个问题
1.由于utl_file操作文件时,实际上操作的是在数据库内映射的文件夹,所以一般建议再人工指定一个文件夹参数;
2.有时候比较危险的操作,想只生成bat文件但不执行;
3.有时候会同时几个会话在执行不同操作系统命令,如果bat文件重复了,可能会导致异常,如果文件名完全随机,在排查故障的时候又方便找到自己需要的bat文件。
所以,可以再加几个参数

CREATE OR REPLACE PROCEDURE TEXT_TO_CMD_P(I_db_Path       IN VARCHAR2, --数据库映射目录
                                          I_cmd_text      IN VARCHAR2,--要执行的操作系统命令
                                          I_file_name     IN VARCHAR2,--bat文件名前缀
                                          I_run           in varchar2 --是否执行bat文件
)

完整源码请从我的github上下载
https://github.com/Dark-Athena/text_to_cmd-oracle

目前该过程暂只支持windows,理论上linux也是可以支持的,但我手上暂时无linux的环境,以后会考虑更新一版自适应操作系统的。

注意:
1.命令中不能存在用户交互式操作,且命令执行完后必须确保操作系统的进程会退出,或者强制在bat文件末尾再补个exit,否则会出现程序一直在执行的情况
2.windows环境中,ORACLE数据库大多是用的system用户,该用户几乎是windows的最高权限用户,所以执行操作系统命令要慎重。
3.由于是在oracle数据库执行的对应的操作系统用户下创建的操作系统进程,所以其他的操作系统用户是无法看到对应的操作命令执行窗口的
4.建议在存储过程正式执行前,确保生成的bat文件内容的正确性

另外,还可以通过调用java再调用操作系统命令,但是授权会比较麻烦,网上可以搜索到比较完整的资料,这里就不赘述了。

posted on 2021-10-03 20:39  DarkAthena  阅读(201)  评论(0编辑  收藏  举报

导航