Home » SQL & PL/SQL » SQL & PL/SQL » Run external job with DBMS_SCHEDULER (Oracle 10.2.0.3.0; MS Windows Server 2003)
Run external job with DBMS_SCHEDULER [message #552207] Tue, 24 April 2012 06:07 Go to next message
Littlefoot
Messages: 21826
Registered: June 2005
Location: Croatia, Europe
Senior Member
Account Moderator
A few more details about the environment:
  • A database server OS is MS Windows Server 2003 Standard Edition Service Pack 2
  • It runs an Oracle database ver. 10.2.0.3.0
  • Client PC (the one I'm working on) is MS Windows 7 Enterprise Edition



Until recently, I only knew that DBMS_SCHEDULER enables you to run operating system programs. However, that was just pure theory for me as I never had to implement that.

Obviously, I can't make it work (otherwise you wouldn't read this story).

Here's what I'm trying to do. It is an Apex application that (among other stuff) is supposed to upload images to an application server.

  • user browses images on his own computer and selects one by one into file browse items
  • once he's done, he pushes the UPLOAD button
  • using a stored procedure, images are copied from the Apex WWV_FLOW_FILES table to a directory located on a database server

So far, so good. These images require additional processing (consecutive resizing, copying to different directories on both application and database server).

The above is done by a (Win)do(w)s batch script (.BAT), and it does its job correctly. It is not a problem to schedule that BAT script using Windows' Task Scheduler, but the idea is to make everything "now" (i.e. when the user pushes that UPLOAD Apex button).

Therefore, I thought that DBMS_SCHEDULER might do the job. Here's what I've done.
  • a database user (which is the Apex application's underlying schema) has the following privileges: CREATE JOB, CREATE EXTERNAL JOB
  • on the database server, OracleJobSchedulerORA10 service is started
  • in order to make it simpler, I created a small batch script that copies one image to anoter:
    REM a.bat
    
    copy ts3032-1.jpg slika.jpg

    The source image exists in that directory:
    D:\GIS\Slike_4005_upload>dir /b *.jpg
    TS3032-1.jpg

    The script actually works; no problem with that:
    D:\GIS\Slike_4005_upload>a
    
    D:\GIS\Slike_4005_upload>copy ts3032-1.jpg slika.jpg
            1 file(s) copied.
    
    D:\GIS\Slike_4005_upload>dir /b *.jpg
    slika.jpg
    TS3032-1.jpg
    
    D:\GIS\Slike_4005_upload>del slika.jpg


Now, let's create a job.
SQL> select sysdate from dual;

SYSDATE
-------------------
24.04.2012 12:34:05

SQL> begin
  2    dbms_scheduler.create_job
  3      (job_name            =>  'myjob',
  4       job_type            =>  'EXECUTABLE',
  5       job_action          =>  'c:\windows\system32\cmd.exe',
  6       number_of_arguments =>   3,
  7       enabled             =>   false,
  8       auto_drop           =>   true
  9      );
 10
 11    dbms_scheduler.set_job_argument_value('myjob', 1, '/q');
 12    dbms_scheduler.set_job_argument_value('myjob', 2, '/c');
 13    dbms_scheduler.set_job_argument_value('myjob', 3, 'd:\gis\slike_4005_upload\a.bat >nul');
 14
 15    dbms_scheduler.enable('myjob');
 16  end;
 17  /

PL/SQL procedure successfully completed.

SQL> select to_char(log_date, 'hh24:mi:ss') dat,
  2    status,
  3    additional_info
  4  from user_scheduler_job_run_details o
  5  where job_name = 'MYJOB'
  6    and log_id = (select max(log_id) from user_scheduler_job_run_details o1
  7                  where o1.job_name = o.job_name);

DAT      STATUS     ADDITIONAL_INFO
-------- ---------- --------------------------------------------------
12:34:13 FAILED     ORA-27369: job of type EXECUTABLE failed with exit
                     code: Incorrect function.


SQL>

I read the DBMS_SCHEDULER documentation, as well as numerous discussions, suggestions etc. found on the Internet (one of frequently mentioned is this OTN forums topic) and I *think* I followed instructions correctly. However, I'm stuck with the above error (of course, A.BAT didn't do anything).

What did I do?
  • JOB_STATUS has to be 'executable'
  • JOB_ACTION: it is suggested that one should rather supply arguments later than having it all in the same JOB_ACTION line. Therefore, I'm just calling CMD.EXE.
    (I tried to put everything into the same line - no difference.)
    CMD.EXE path indicates the database server directory.
  • ENABLED should be set to FALSE, as I'm not over yet
  • SET_JOB_ARGUMENT_VALUE (1 and 2): Internet sources suggest that /q /c should be used.
    /C Carries out the command specified by string and then terminates
    /Q Turns echo off
  • SET_JOB_ARGUMENT_VALUE (3): >nul
    Many people said that it helped - for example, here:Quote:

    The redirection of the batch's output to nul (> nul) seems to be important in order for the function to run. When I omitted it, I received an ORA-27369: job of type EXECUTABLE failed with exit code: Incorrect function ORA-27369: job of type EXECUTABLE failed with exit code: Incorrect function.

    It didn't help me.

    Similarly to CMD.EXE, the path indicates a directory located on a database server.

    If it makes any difference, Oracle directory object is created on the same operating system directory and it works fine (tested while uploading images from my own PC to a server using Apex):
    SQL> select * from all_directories;
    
    OWNER    DIRECTORY_NAME                 DIRECTORY_PATH
    -------- ------------------------------ ------------------------------
    SYS      SLIKE_4005_UPLOAD              d:\gis\slike_4005_upload

  • Finally, ENABLE the job

Among other sources, this one: Start OS Jobs From Within Oracle says - for Windows OS:Quote:

- The service OracleJobScheduler%ORACLE_SID% must be running
- User (and thus indirectly the group) must be configured via that service (Properties => Log On)

The first one is OK, I already said that. I logged onto a database server as an Administrator when starting the service. However, I don't really understand the second one. WHICH user? Administrator? I'm not even sure that this is an issue.

I'm kind of lost now. Could someone assist, please?
Re: Run external job with DBMS_SCHEDULER [message #552215 is a reply to message #552207] Tue, 24 April 2012 06:30 Go to previous messageGo to next message
John Watson
Messages: 8988
Registered: January 2010
Location: Global Village
Senior Member
Hi, man. this works for me:
exec dbms_scheduler.drop_job('tryit')
exec dbms_scheduler.drop_credential('my_cred')

exec dbms_scheduler.create_credential('my_cred','jwdell\john','pass')

exec dbms_scheduler.create_job(-
job_name=>'tryit',-
job_type=>'executable',-
job_action=>'c:\windows\system32\cmd.exe',-
number_of_arguments => 2,-
enabled=>false,-
auto_drop=>false,-
credential_name=>'my_cred')

exec dbms_scheduler.set_job_argument_value('tryit',1,'/c');
exec dbms_scheduler.set_job_argument_value('tryit',2,'dir');

exec dbms_scheduler.enable('tryit')

select job_name, status, error#, actual_start_date, additional_info
from user_scheduler_job_run_details where job_name='TRYIT';

the credential stuff is because I'm using 11.2, you don;t have that available in 10g. Here's the output from the query at the end:
JOB_NAME
---------------------------------------------------------------------------------------------------

STATUS                             ERROR# ACTUAL_START_DATE
------------------------------ ---------- ---------------------------------------------------------
ADDITIONAL_INFO
---------------------------------------------------------------------------------------------------

TRYIT
SUCCEEDED                               0 24-APR-12 12.21.09.576000 EUROPE/LISBON
EXTERNAL_LOG_ID="job_89757_8115",
USERNAME="jwdell\john"

TRYIT
FAILED                              27370 24-APR-12 12.16.27.870000 EUROPE/LISBON
ORA-27370: job slave failed to launch a job of type EXECUTABLE
ORA-27300: OS system dependent operation:accessing job scheduler service failed with status: 2
ORA-27301: OS failure message: The system cannot find the file specified.
ORA-27302: failure occurred at: sjsec 6a
ORA-27303: additional information: The system cannot find the file specified.


orcl>
orcl>
the first run failed because I had no credentials. Then I created them and it worked. Could that be your problem? In 10g, I think you set credentials in %ORACLE_HOME%\rdbms\admin\externaljob.ora.
And by the way, my Windows OracleJobSchedulerORCL service is disabled.
Re: Run external job with DBMS_SCHEDULER [message #552219 is a reply to message #552215] Tue, 24 April 2012 06:55 Go to previous messageGo to next message
Littlefoot
Messages: 21826
Registered: June 2005
Location: Croatia, Europe
Senior Member
Account Moderator
Thank you, John.

When I try with your simple DIR command, status is SUCCEEDED! However, bad luck when calling a batch script. Could you, please, test it once again, but this time call a simple batch script (doesn't matter what it does)? What is the outcome?

P.S. There's no EXTERNALJOB.ORA file in the whole %ORACLE_HOME% ...
Re: Run external job with DBMS_SCHEDULER [message #552222 is a reply to message #552219] Tue, 24 April 2012 07:00 Go to previous messageGo to next message
Littlefoot
Messages: 21826
Registered: June 2005
Location: Croatia, Europe
Senior Member
Account Moderator
Huh, it appears that
dbms_scheduler.set_job_argument_value('myjob', 3, 'a.bat >nul');
(note: I removed the path to A.BAT) works OK when I put A.BAT into c:\windows\system32 directory. It won't work if I put A.BAT into, for example, c:\. Is it really supposed to work that way?
Re: Run external job with DBMS_SCHEDULER [message #552223 is a reply to message #552219] Tue, 24 April 2012 07:02 Go to previous messageGo to next message
Michel Cadot
Messages: 68767
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator
Maybe with just an "exit" at the end of the batch file...

Regards
Michel
Re: Run external job with DBMS_SCHEDULER [message #552227 is a reply to message #552223] Tue, 24 April 2012 07:07 Go to previous messageGo to next message
Littlefoot
Messages: 21826
Registered: June 2005
Location: Croatia, Europe
Senior Member
Account Moderator
Thank you, Michel, but no, unfortunately that makes no difference.
Re: Run external job with DBMS_SCHEDULER [message #552230 is a reply to message #552222] Tue, 24 April 2012 07:12 Go to previous messageGo to next message
John Watson
Messages: 8988
Registered: January 2010
Location: Global Village
Senior Member
So you have it working? As a work around to that silly location being required, could you create the Windows equivalent of a soft link (I think it is called a "junction"?) in \windows\system32

In the back of my mind (which is very dark and gloomy place) I have a memory of getting this to work with release 10.1 on Windows. Rather than specifying the job_action as cmd.exe and passing the batch file as a parameter, I gave the batch file (with a full path, which could be anywhere) as the job_action. It worked, if I set the COMSPEC environment variable to C:\wherever\COMMAND.COM as the first line of the batch file. A bit like having #!/bin/sh in a shell script.

Re: Run external job with DBMS_SCHEDULER [message #552231 is a reply to message #552230] Tue, 24 April 2012 07:21 Go to previous messageGo to next message
John Watson
Messages: 8988
Registered: January 2010
Location: Global Village
Senior Member
If I specify a batch file c:\tmp\file.bat as the job_action, I get this in user_scheduler_job_run_details:
TRYIT
FAILED                         -1.074E+09 24-APR-12 13.14.09.413000 EUROPE/LISBON
EXTERNAL_LOG_ID="job_89763_8119",
ORA-27369: job of type EXECUTABLE failed with exit code: -10737418
STANDARD_ERROR="Exception 0xc0000005 encountered at address 0x778B653B
Generating core file .\core_jssu_201242413149.dmp"

and furthermore if I place the file in c:\windows\system32 and remove the path from the job action, I get exactly the same error. So you are doing better than me at the moment.

-------------------------
Correction: not "specify a batch file c:\tmp\file.bat as the job_action" above, should be "specify a batch file c:\tmp\file.bat as the second parameter"

[Updated on: Tue, 24 April 2012 07:34]

Report message to a moderator

Re: Run external job with DBMS_SCHEDULER [message #552235 is a reply to message #552231] Tue, 24 April 2012 07:48 Go to previous messageGo to next message
Littlefoot
Messages: 21826
Registered: June 2005
Location: Croatia, Europe
Senior Member
Account Moderator
Great ideas, thank you!

COMSPEC is already set (as an environment variable) and points to c:\windows\system32\cmd.exe.

JUNCTION is something I never heard of before; I Googled a little bit and downloaded junction.exe from Windows SysInternals; I suppose I'll have to research it a little bit further.

Here's something that seems to be working (unfortunately, just a workaround): I created another batch script (call.bat) and put it into c:\windows\system32. I call that script from DBMS_SCHEDULER, and newly created batch script calls the "original" one located on the D disk:
DBMS_SCHEDULER   ->   c:\windows\system32\call.bat   ->   d:\gis\slike_4005_upload\a.bat

REM call.bat

call d:\gis\slike_4005_upload\a.bat


Although it is not perfect, it actually works, which is MUCH better than anything I managed to do for the past 2 days. I always thought that it must be some missing privileges or stuff. Batch file location never crossed my mind (maybe it would if D disk was mapped, but no - it is database server's disk).

Once again, thank you very much for suggestions you provided. If anyone knows how to make the original script work, please, say so. Otherwise, I'm quite happy with the current workaround.

P.S. I hope that my "real" batch script won't fail. I'll test that tomorrow.

P.P.S. Why another, CALL.BAT script? I'd rather not keep my stuff in \system32 directory. Slippery fingers on a slippery keyboard aren't very healthy.

[Updated on: Tue, 24 April 2012 07:58]

Report message to a moderator

Re: Run external job with DBMS_SCHEDULER [message #552285 is a reply to message #552235] Tue, 24 April 2012 21:12 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9106
Registered: November 2002
Location: California, USA
Senior Member
Littlefoot,

Your original script, changing the directories and jpg file to match those on my system, produces the same error that you originally posted. If I just use complete directory paths within the a.bat file, then it runs without error and copies the file. Please see the demonstration below. The OracleJobSchedulerORCL service was running. I used dbms_lock.sleep to wait long enough for the job to finish before checking the results, otherwise you may be viewing the results of the previous run.

SCOTT@orcl_11gR2> host type a.bat
copy c:\image_dir\junk.jpg c:\image_dir\junka.jpg


SCOTT@orcl_11gR2> host dir c:\image_dir
 Volume in drive C has no label.
 Volume Serial Number is F0BB-93C9

 Directory of c:\image_dir

04/24/2012  07:04 PM    <DIR>          .
04/24/2012  07:04 PM    <DIR>          ..
10/15/2010  05:10 PM            30,549 JUNK.JPG
               1 File(s)         30,549 bytes
               2 Dir(s)  397,977,796,608 bytes free

SCOTT@orcl_11gR2> begin
  2    dbms_scheduler.create_job
  3      (job_name            =>  'myjob',
  4       job_type            =>  'EXECUTABLE',
  5       job_action          =>  'c:\windows\system32\cmd.exe',
  6       number_of_arguments =>   3,
  7       enabled             =>   false,
  8       auto_drop           =>   true
  9      );
 10
 11    dbms_scheduler.set_job_argument_value('myjob', 1, '/q');
 12    dbms_scheduler.set_job_argument_value('myjob', 2, '/c');
 13    dbms_scheduler.set_job_argument_value('myjob', 3, 'c:\my_oracle_files\a.bat >nul');
 14
 15    dbms_scheduler.enable('myjob');
 16  end;
 17  /

PL/SQL procedure successfully completed.

SCOTT@orcl_11gR2> exec dbms_lock.sleep (5)

PL/SQL procedure successfully completed.

SCOTT@orcl_11gR2> select to_char(log_date, 'hh24:mi:ss') dat,
  2         status,
  3         additional_info
  4  from   user_scheduler_job_run_details o
  5  where  job_name = 'MYJOB'
  6    and  log_id = (select max(log_id) from user_scheduler_job_run_details o1
  7                   where o1.job_name = o.job_name)
  8  /

DAT      STATUS
-------- ------------------------------
ADDITIONAL_INFO
--------------------------------------------------------------------------------
19:04:51 SUCCEEDED



1 row selected.

SCOTT@orcl_11gR2> host dir c:\image_dir
 Volume in drive C has no label.
 Volume Serial Number is F0BB-93C9

 Directory of c:\image_dir

04/24/2012  07:04 PM    <DIR>          .
04/24/2012  07:04 PM    <DIR>          ..
10/15/2010  05:10 PM            30,549 JUNK.JPG
10/15/2010  05:10 PM            30,549 junka.jpg
               2 File(s)         61,098 bytes
               2 Dir(s)  397,976,641,536 bytes free

SCOTT@orcl_11gR2>

Re: Run external job with DBMS_SCHEDULER [message #552305 is a reply to message #552285] Wed, 25 April 2012 00:54 Go to previous message
Littlefoot
Messages: 21826
Registered: June 2005
Location: Croatia, Europe
Senior Member
Account Moderator
Barbara

If I just use complete directory paths within the a.bat file, then it runs without error and copies the file


Thank you, Barbara!

That seems to be THE ULTIMATE solution! Based on your suggestion, I slightly modified A.BAT and - instead of specifying the whole path, I set the "current" directory at the beginning of the batch file:
REM a.bat

d:
cd d:\gis\slike_4005_upload\

copy ts3032-1.jpg slika.jpg

SQL> begin
  2    dbms_scheduler.create_job
  3      (job_name            =>  'myjob',
  4       job_type            =>  'EXECUTABLE',
  5       job_action          =>  'c:\windows\system32\cmd.exe',
  6       number_of_arguments =>   3,
  7       enabled             =>   false,
  8       auto_drop           =>   true
  9      );
 10
 11    dbms_scheduler.set_job_argument_value('myjob', 1, '/q');
 12    dbms_scheduler.set_job_argument_value('myjob', 2, '/c');
 13    dbms_scheduler.set_job_argument_value('myjob', 3, 'd:\gis\slike_4005_upload\a.bat >nul');
 14
 15    dbms_scheduler.enable('myjob');
 16  end;
 17  /

PL/SQL procedure successfully completed.

SQL>
SQL> select to_char(log_date, 'hh24:mi:ss') dat,
  2    status,
  3    additional_info
  4  from user_scheduler_job_run_details o
  5  where job_name = 'MYJOB'
  6    and log_id = (select max(log_id) from user_scheduler_job_run_details o1
  7                  where o1.job_name = o.job_name);

DAT      STATUS     ADDITIONAL_INFO
-------- ---------- ----------------------------------------
07:51:44 SUCCEEDED

SQL>


Thanks again, everyone. Much obliged.
Previous Topic: procedure to call user defined function (merged 2)
Next Topic: Privileges for AWR Report
Goto Forum:
  


Current Time: Thu Aug 28 11:28:56 CDT 2025