• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • Submit Job Schedule Entries Immediately

    December 1, 2004 Ted Holt

    The code for this article is available for download.

    You can buy better job schedulers than the one that comes bundled with OS/400. Unfortunately for many of us, the OS/400 job scheduler is the only one we’re permitted to use. Because I recently found myself forced to work within that restriction, I wrote a command to overcome one of the built-in job scheduler’s limitations. Later I discovered that my new utility overcame a second limitation. It occurred to me that some of you might like to have this utility.

    In “Job Scheduler’s Other Defaults,” I explained to Beau that the OS/400 job scheduler runs a Submit Job (SBMJOB) command, filling in certain parameters with non-default values. A problem occurs when someone needs to submit a scheduled job to run outside of the regularly scheduled time. The Work with Job Schedule Entries panel includes option 10, “submit immediately,” which at first seems to address the need, but doesn’t really. The Submit Immediately option runs SBMJOB with SBMJOB’s usual default parameter values, not the non-default parameter values that that the job scheduler uses. This means that the job scheduler does not include an option to immediately submit an entry in the same way the job scheduler normally submits the entry. This is the limitation I needed to overcome.

    For this reason, I wrote the Submit Job Schedule Entry (SBMJOBSCDE) utility. It retrieves a job scheduler entry and builds a SBMJOB command, filling in the parameters with the non-default values the job scheduler uses. The utility consists of three objects: the SBMJOBSCDE command, an OPM CL command-processing program named JOBSCDE1C, and a help panel group called JOBSCDE1H.

    SBMJOBSCDE is easy to use. It has only two parameters. The first is the name of the entry as it appears in the job scheduler. The second parameter works only in interactive mode. It permits you to prompt the generated SBMJOB command so you can make changes before the new job is submitted to batch. Here’s the source code.

    /* ==================================================== */
    /* Submit a job schedule entry for immediate execution. */
    /* ==================================================== */
    /* To create:                                           */
    /*     CRTCMD CMD(xxx/SBMJOBSCDE)                       */
    /*            PGM(xxx/JOBSCDE1C)                        */
    /*            SRCFILE(xxx/QCMDSRC)                      */
    /*            HLPPNLGRP(JOBSCDE1H)                      */
    /*            HLPID(*CMD)                               */
    /* ==================================================== */
    CMD        PROMPT('Submit Job Schedule Entry')
    PARM       KWD(JOB) TYPE(*CHAR) LEN(10) MIN(1) +
                 EXPR(*YES) PROMPT('Job schedule entry name')
    PARM       KWD(PROMPT) TYPE(*CHAR) LEN(4) RSTD(*YES) +
                 DFT(*NO) VALUES(*YES *NO) EXPR(*YES) +
                 PROMPT('Prompt before submitting?')
    

    The CL program uses the List Job Schedule Entries (QWCLSCDE) API to retrieve the job schedule entry information into user space QTEMP/SBMJOBSCDE. It extracts that information from the user space to build the SBMJOB command.

    /* ==================================================== */
    /* Submit a job schedule entry for immediate execution. */
    /* ==================================================== */
    /* To compile:                                          */
    /*      CRTCLPGM PGM(xxx/JOBSCDE1C)                     */
    /*               SRCFILE(xxx/QCLSRC)                    */
    /*               SRCMBR(JOBSCDE1C)                      */
    /* ==================================================== */
    
    pgm parm(&inJobScdE &inPrompt)
    
       dcl &inJobScdE   *char     10
       dcl &inPrompt    *char      4
    
       dcl &UsrSpcName  *char     10  'SBMJOBSCDE'
       dcl &UsrSpcLib   *char     10  'QTEMP'
       dcl &UsrSpc      *char     20
       dcl &FmtName     *char      8  'SCDL0200'
       dcl &NbrEntries  *dec      10
       dcl &Offset      *dec      10
       dcl &EntryLen    *dec      10
       dcl &Continue    *char     16
       dcl &StartPos    *dec       5
       dcl &UsrSpcData  *char x'1000'
       dcl &UsrSpcSize  *char      4  x'00001000'
       dcl &Error       *char     16  x'00000010'
       dcl &JobType     *char      1
    
       dcl &Cmd         *char    512
       dcl &CmdLen      *dec       3
       dcl &InfoStatus  *char      1
       dcl &JobName     *char     10
       dcl &JobQ        *char     10
       dcl &JobQLib     *char     10
       dcl &JobD        *char     10
       dcl &JobDLib     *char     10
       dcl &MsgQ        *char     10
       dcl &MsgQLib     *char     10
       dcl &UsrPrf      *char     10
    
       dcl &CmdString   *char   4096
       dcl &Quote       *char      1  ''''
    
       dcl &Abending    *lgl
       dcl &MsgID       *char      7
       dcl &MsgDta      *char    256
       dcl &MsgF        *char     10
       dcl &MsgFLib     *char     10
       dcl &MsgKey      *char      4
       dcl &RtnType     *char      2
       dcl &PgmName     *char     10
       dcl &Sender      *char     80
    
       monmsg cpf0000 exec(goto abend)
    
       /* retrieve the program name */
       sndpgmmsg msg(' ') topgmq(*same) msgtype(*info) keyvar(&MsgKey)
       rcvmsg    pgmq(*same) msgtype(*info) sender(&Sender) rmv(*yes)
       chgvar    &PgmName   %sst(&Sender 56 10)
    
       /* create a temporary user space                 */
       /* and load it with job schedule information     */
    
       chgvar     &UsrSpc   (&UsrSpcName *cat &UsrSpcLib)
    
       chkobj &UsrSpcLib/&UsrSpcName *usrspc
       monmsg cpf0000 exec(do)
          call quscrtus (&UsrSpc ' ' &UsrSpcSize ' ' *all &Error)
       enddo
       call qwclscde  (&UsrSpc &FmtName &inJobScdE &Continue &Error)
       call qusrtvus  (&UsrSpc x'00000001' &UsrSpcSize &UsrSpcData &Error)
    
       chgvar &NbrEntries   %bin(&UsrSpcData 133 4)
       if (&NbrEntries *lt 1) do
          chgvar var(&MsgDta) value('Job schedule entry' *bcat &inJobScdE +
                                    *bcat 'could not be found.')
          sndpgmmsg  msgid(cpf9897)  msgf(qcpfmsg)   msgtype(*diag) +
                       msgdta(&MsgDta)
          goto Escape
       enddo
    
    /* extract job info from the job schedule entry */
       chgvar &Offset       %bin(&UsrSpcData 125 4)
       chgvar &EntryLen     %bin(&UsrSpcData 137 4)
    
       chgvar &StartPos     (&Offset + 1)
       chgvar &InfoStatus   %sst(&UsrSpcData &StartPos 1)
       chgvar &StartPos     (&Offset + 2)
       chgvar &JobName      %sst(&UsrSpcData &StartPos 10)
       chgvar &StartPos     (&Offset + 198)
       chgvar &JobQ         %sst(&UsrSpcData &StartPos 10)
       chgvar &StartPos     (&Offset + 208)
       chgvar &JobQLib      %sst(&UsrSpcData &StartPos 10)
       chgvar &StartPos     (&Offset + 527)
       chgvar &JobD         %sst(&UsrSpcData &StartPos 10)
       chgvar &StartPos     (&Offset + 537)
       chgvar &JobDLib      %sst(&UsrSpcData &StartPos 10)
       chgvar &StartPos     (&Offset + 547)
       chgvar &UsrPrf       %sst(&UsrSpcData &StartPos 10)
       chgvar &StartPos     (&Offset + 557)
       chgvar &MsgQ         %sst(&UsrSpcData &StartPos 10)
       chgvar &StartPos     (&Offset + 567)
       chgvar &MsgQLib      %sst(&UsrSpcData &StartPos 10)
       chgvar &StartPos     (&Offset + 641)
       chgvar &CmdLen       %bin(&UsrSpcData &StartPos 4)
       chgvar &StartPos     (&Offset + 645)
       chgvar &Cmd          %sst(&UsrSpcData &StartPos &CmdLen)
    
    /* Was prompting requested? */
       rtvjoba type(&JobType)
       if (&JobType *eq '1') do /* Interactive job */
          if ((%sst(&inPrompt 2 1) *eq 'Y') +
          *or (%sst(&inPrompt 2 1) *eq 'y')) do
             chgvar  &CmdString '?'
          enddo
       enddo
    
    /* build a command string from the job schedule entry */
       chgvar  &CmdString (&CmdString *tcat 'SBMJOB JOB(' +
                           *cat &JobName *tcat ')')
    
       chgvar  &CmdString (&CmdString *bcat 'JOBD(')
       if (%sst(&JobD 1 1) *ne '*') do
          chgvar  &CmdString (&CmdString *tcat &JobDLib *tcat '/')
       enddo
       chgvar  &CmdString (&CmdString *tcat &JobD *tcat ')')
    
       chgvar  &CmdString (&CmdString *bcat 'JOBQ(')
       if (%sst(&JobQ 1 1) *ne '*') do
          chgvar  &CmdString (&CmdString *tcat &JobQLib *tcat '/')
       enddo
       chgvar  &CmdString (&CmdString *tcat &JobQ *tcat ')')
    
       chgvar  &CmdString (&CmdString *bcat 'CMD(' +
                           *cat %sst(&Cmd 1 &CmdLen) +
                           *cat ')')
    
       chgvar  &CmdString (&CmdString *bcat 'USER(' *cat &UsrPrf *cat ')')
    
       chgvar  &CmdString (&CmdString *bcat 'MSGQ(')
       if (%sst(&MsgQ 1 1) *ne '*') do
          chgvar  &CmdString (&CmdString *tcat &MsgQLib *tcat '/')
       enddo
       chgvar  &CmdString (&CmdString *tcat &MsgQ *tcat ')')
    
       chgvar  &CmdString (&CmdString *bcat 'SYSLIBL(*SYSVAL) +
                              CURLIB(*USRPRF) INLLIBL(*JOBD) +
                              PRTDEV(*JOBD) OUTQ(*JOBD) +
                              PRTTXT(*JOBD) RTGDTA(*JOBD) +
                              SRTSEQ(*USRPRF) LANGID(*USRPRF) +
                              CNTRYID(*USRPRF) CCSID(*USRPRF)')
    
       call   qcmdexc   (&CmdString 4096)
       monmsg cpf6801
       rcvmsg     msgtype(*last) msgdta(&MsgDta) msgid(&MsgID) +
                     rtntype(&RtnType) +
                     msgf(&MsgF) sndmsgflib(&MsgFLib)
       sndpgmmsg  msgid(&MsgID)  msgf(&MsgF) msgtype(*comp) +
                    msgdta(&MsgDta)
       return
    
       /* Routine to handle unexpected errors */
    Abend:
          if &Abending then(return)
          chgvar   &Abending '1'
    
    ForwardMsg:
          rcvmsg     msgtype(*any) msgdta(&MsgDta) msgid(&MsgID) +
                        rtntype(&RtnType) +
                        msgf(&MsgF) sndmsgflib(&MsgFLib)
          if ((&RtnType *eq '02') *or   /* diagnostic */ +
              (&RtnType *eq '15') *or (&RtnType *eq '17')) do  /* *escape */
             sndpgmmsg  msgid(&MsgID)  msgf(&MsgF)   msgtype(*diag) +
                       msgdta(&MsgDta)
          enddo
          if (&RtnType *ne '  ') then(goto ForwardMsg)
    Escape:
       sndpgmmsg  msgid(cpf9898) msgf(qcpfmsg) msgtype(*escape) +
                    msgdta('Program' *bcat &PgmName *bcat +
                           'ended abnormally')
    endpgm
    

    The command is easy enough to use, but I put together some brief help text anyway. Store it in member JOBSCDE1H.

    .* ====================================================================
    .* Help text for the SBMJOBSCDE command
    .* ====================================================================
    .* To create:
    .*      CRTPNLGRP PNLGRP(xxx/JOBSCDE1H)
    .*                SRCFILE(xxx/QPNLSRC)
    .*                SRCMBR(JOBSCDE1H)
    .* ====================================================================
    
    :PnlGrp.
    
    
    :Help Name = 'SBMJOBSCDE' .Submit Job Schedule Entry - Help
    
    :P.
    The Submit Job Schedule Entry (SBMJOBSCDE) command allows you to submit
    a job scheduler entry using the parameter values the job scheduler
    applies to the SBMJOB command. SBMJOBSCDE allows you to run a scheduled
    job on demand in the same way it would run if the job scheduler started
    it.
    
    :EHelp.
    
    :Help Name = 'SBMJOBSCDE/Job' .Job name (JOB) - Help
    :XH3 .Job entry (JOB)
    
    :P.
    The name of the job as it is known to the job scheduler.
    
    :P.
    This is a required parameter.
    
    :EHelp.
    
    :Help Name = 'SBMJOBSCDE/PROMPT' .Prompt command (PROMPT) - Help
    :XH3 .Prompt command (PROMPT)
    
    :P.
    This parameter applies to interactive execution of SBMJOBSCDE only.
    It allows you to modify the generated SBMJOB comamnd before submitting
    the job to batch for execution.
    
    :P.
    The possible values are:
    
    :Parml.
    :pt.:pk def.*NO:epk.
    :pd.SBMJOB will not be prompted before execution.
    :pt.:pk.*YES:epk.
    :pd.SBMJOB will be prompted for execution. You will be allowed to
    modify parameter values.
    :EParmL.
    
    :EHelp.
    
    :EPnlGrp. 
    

    I mentioned that my new utility overcame a second limitation. After I wrote SBMJOBSCDE, I realized I had found the answer to the problem I wrote about in “Scheduling a Job to Run More than Once a Day.” In a follow-up to that article, reader Rocky suggested creating multiple, identical job schedule entries in order to run a job schedule entry more than once a day. The problem with that approach is that changing one entry means having to change them all.


    SBMJOBSCDE addresses this problem as well. Create one entry with the proper settings. Make the others run SBMJOBSCDE to kick off the original entry at other times.

    So far I have been pleased with SBMJOBSCDE. This utility has worked correctly in all my tests and in production. I hope some of you will find it helpful as well. Please contact me with bug reports or suggestions for improvements, if you have a better idea, or just to let me know it’s helped you.

    Ted Holt is editor of Four Hundred Guru. Click here to contact Ted Holt by e-mail.

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags:

    Sponsored by
    Maxava

    Disaster Recovery Strategy Guide for IBM i

    Practical tools to implement disaster recovery in your IBM i environment. Fully optimized to include cloud recovery, replication and monitoring options.

    Download NOW!

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Pat Townsend Launches Stand-Alone AES/400 Encryption Solution Choose Wisely: High Availability Performance and Reliability Issues

    Leave a Reply Cancel reply

Volume 4, Number 40 -- December 1, 2004
THIS ISSUE
SPONSORED BY:

Linoma Software
WorksRight Software
Guild Companies

Table of Contents

  • Submit Job Schedule Entries Immediately
  • V5R3 CL Enhancements on V5R2
  • Admin Alert: Tips for Dealing with Deleted Records in AS/400 Files

Content archive

  • The Four Hundred
  • Four Hundred Stuff
  • Four Hundred Guru

Recent Posts

  • IBM Unveils Manzan, A New Open Source Event Monitor For IBM i
  • Say Goodbye To Downtime: Update Your Database Without Taking Your Business Offline
  • i-Rays Brings Observability To IBM i Performance Problems
  • Another Non-TR “Technology Refresh” Happens With IBM i TR6
  • IBM i PTF Guide, Volume 27, Number 18
  • Will The Turbulent Economy Downdraft IBM Systems Or Lift It?
  • How IBM Improved The Database With IBM i 7.6
  • Rocket Celebrates 35th Anniversary As Private Equity Owner Ponders Sale
  • 50 Acres And A Humanoid Robot With An AI Avatar
  • IBM i PTF Guide, Volume 27, Number 17

Subscribe

To get news from IT Jungle sent to your inbox every week, subscribe to our newsletter.

Pages

  • About Us
  • Contact
  • Contributors
  • Four Hundred Monitor
  • IBM i PTF Guide
  • Media Kit
  • Subscribe

Search

Copyright © 2025 IT Jungle