目 录CONTENT

文章目录

【ORACLE】有时候看看oracle官方安装包的代码也能有一些百度上找不到的收获(数据库执行linux命令)

DarkAthena
2021-10-18 / 0 评论 / 0 点赞 / 804 阅读 / 0 字

今天在$ORACLE_HOME/oml4py/server/pyqatmlcfg.sql 中看到了一段这样的代码

declare
  pyqdmp_dir varchar2(4000);
  pdb_dir varchar2(4000);
  load_script varchar2(32767);
  sched_job_name varchar2(30);
  out_File  UTL_FILE.FILE_TYPE;
  l_fexists boolean;
  l_flen    number;
  l_bsize   number;
begin
  pyqdmp_dir := '&dmpf_dir';

  select directory_path into pdb_dir
  from dba_directories
  where directory_name='DATA_PUMP_DIR';

  load_script :=
'#!/bin/bash
if [ -d ' || pdb_dir || ' ]; then
  cp -f ' || pyqdmp_dir || '/' || '&dump_file' || ' ' || pdb_dir || '/' || '&dump_file' || '
fi
exit 0 ';

  -- Generate a name for the scheduler job
  sched_job_name := dbms_scheduler.generate_job_name(prefix => 'OML4PY_');

  dbms_output.put_line(load_script);
  out_File := UTL_FILE.FOPEN('DATA_PUMP_DIR', 'load_' || sched_job_name || '.log' , 'a');
  UTL_FILE.PUT_LINE(out_file , load_script);
  UTL_FILE.FCLOSE(out_file);

  -- Create a scheduler job 
  DBMS_SCHEDULER.create_job(
    job_name            => sched_job_name,
    job_type            => 'EXECUTABLE',
    job_action          => '/bin/sh',
    number_of_arguments => 2,
    enabled             => false,
    auto_drop           => true);

  -- Set the arguments for the scheduler job 
  DBMS_SCHEDULER.set_job_argument_value(sched_job_name, 1, '-c');
  DBMS_SCHEDULER.set_job_argument_value(sched_job_name, 2, load_script);

  DBMS_SCHEDULER.enable(name => sched_job_name);
  -- Run the scheduler job in the current session
  DBMS_SCHEDULER.run_job(job_name => sched_job_name,
                         use_current_session => true);

  UTL_FILE.FGETATTR('DATA_PUMP_DIR', '&dump_file', l_fexists, l_flen, l_bsize);
  out_File := UTL_FILE.FOPEN('DATA_PUMP_DIR', 'load_' || sched_job_name || '.log' , 'a');
  IF l_fexists THEN
    UTL_FILE.PUT_LINE(out_file , '### SUCCEEDED ###');
  ELSE
    UTL_FILE.PUT_LINE(out_file , '### FAILED ###');
  END IF;

  UTL_FILE.FCLOSE(out_file);
exception
  when others then
    -- dbms_scheduler may throw ORA-27369 when running on post-install
    -- Trap ORA-27369 and re-throw ORA-20101 if dmp file does not exist
    if SQLCODE = -27369 then
      UTL_FILE.FGETATTR('DATA_PUMP_DIR', '&dump_file', l_fexists, l_flen, l_bsize);
      out_File := UTL_FILE.FOPEN('DATA_PUMP_DIR', 'load_' || sched_job_name || '.log' , 'a');
      IF l_fexists THEN
        UTL_FILE.PUT_LINE(out_file , '### SUCCEEDED ###');
        UTL_FILE.FCLOSE(out_file);
      ELSE
        UTL_FILE.PUT_LINE(out_file , '### FAILED ###');
        UTL_FILE.FCLOSE(out_file);
        raise_application_error(-20101, 'load_' || sched_job_name ||
                                ' failed to copy ' || '&dump_file');
      END IF;
    else
      raise;
    end if;
end;
/

这段代码是在数据库中,通过schedulejob来执行操作系统命令,和我之前这篇文章很类似【AIO】使用ORACLE存储过程执行windows操作系统命令
但是我写的是在windows环境下,我也一直在找怎么在linux环境下执行命令。但是网上搜到的全部都是执行sh文件,sh文件还得授权。而且在操作系统中能直接执行的命令在schedulejob中却不能直接执行。不过一看这段代码思路就打开了。

注意看load_script参数,这个参数内直接就是sh文件内的内容,也就是说,其实我们不需要先生成一个sh文件,而是可以通过set_job_argument_value的方式,直接将sh的内容,传递到/bin/sh执行。

其实对于schedulejob来说,linux和windows的可执行程序是有区别的,windows里bat和exe都能直接运行,而linux里却要通过/bin/sh来运行。对于同样的一条命令 "python --help",直接在windows和linux下都能运行(因为登录linux就是用的shell),但是换到schedulejob中,windows下能执行,linux下提示找不到文件。就算把python的全路径写上去,同样也是提示找不到文件。这也是为什么网上搜到的相关例子全部都是先写个sh文件再去运行它的原因。

有这个例子,我们可以让数据库执行操作系统命令更简单,理论上这个方法对于windows和linux都是通用的,不再需要新建一个目录来存储bat或者sh文件,传入命令直接执行即可,哪怕命令再长而且有换行,只要以参数的形式传入,再长都不怕。

晚点补充实验代码

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin
博主关闭了所有页面的评论