End Active Job within a cl pgm

205 pts.
Tags:
AS/400
I have a job that runs under a sbs that i would like to end within a cl pgm. My issue is when i do endjob job(blahblah), it will pull up duplicate jobs from the outq, then i have to select the active job to end. Kinda defeats the purpose for the pgm. I would like to get away from entering wrkactjob job(blahblah) and placing an option 4 to end the active job if i could. I will note that the job number/user is different for each time the job is active. In short, can this be done?

Thanks.

 



Software/Hardware used:
as400 iseries

Answer Wiki

Thanks. We'll let you know when a new response is added.

when the job you want to end with the CLP is initiated, have it write the job stats to a file, such as:

Job name . . . . . . . . . . . . * Name, *
User . . . . . . . . . . . . . Name
Number . . . . . . . . . . . . 000000-999999

when you want the CLP to cancel that job, read the file and get the current (most recent) iteration of the job to shut down and process the command with the data from the file.

-sarge

Discuss This Question: 5  Replies

 
There was an error processing your information. Please try again later.
Thanks. We'll let you know when a new response is added.
Send me notifications when members answer or reply to this question.

REGISTER or login:

Forgot Password?
By submitting you agree to receive email from TechTarget and its partners. If you reside outside of the United States, you consent to having your personal data transferred to and processed in the United States. Privacy
  • TomLiotta
    You could modify jobs to log some kind of status info as noted in the answer box; but you'd be doing that for every future job that you want to access by program. I'd say it's much better to start with learning how to get what you need without modifying any current programming. There are two general ways to get it done -- use some work management APIs or mess around with things like creating spooled files from WRKACTJOB or WRKSBSJOB and reading through the spooled files. The APIs tend to be a lot cleaner in the long run, more accurate and more immune to upgrades. But they seem to scare a lot of people. The spooled files method seems to be easier because people tend to be already familiar with how they look, while the APIs are unfamiliar. (Once I did my first successful API project, I never considered going back to the spooled files.) Your simplest API route would be through the List Job (QUSLJOB) API. A different API could be more direct, but QUSLJOB is a better starting point. To make QUSLJOB work, two additional APIs -- Create User Space (QUSCRTUS) API and Retrieve User Space (QUSRTVUS) API -- will also be needed. The structure of your new procedure would go something like this:
    1. Create a *USRSPC with QUSCRTUS.
    2. List all jobs with the name of the job that you're interested in.
    3. Loop through the list with QUSRTVUS to see if any of them have *ACTIVE status.
    4. Use the fully-qualified job name from the list to end the *ACTIVE one.
    There are a couple variations depending on what version of i5/OS you're using. If you're at V5R4 or higher, you could use the Retrieve Pointer to User Space (QUSPTRUS) API instead of QUSRTVUS; that lets you simply step through the *USRSPC by adding an offset to a pointer rather than retrieving each list entry into a CL variable. You could also use other work management APIs to access all details of the fully-qualified job name that you retrieved from the *USRSPC before ending the job; that could eliminate a potential problem from someone unexpectedly giving an unrelated job the same name as the one you're interested in. If you want to go with the APIs, there is plenty of help available. CL has done this kind of stuff for a couple decades, so it's not quite out of the question. Tom
    125,585 pointsBadges:
    report
  • PSMurray
    Lotofbad - We have dozens of jobs like this that run in a special "work" SBS. We control these jobs by a data area of the same name as the CL. We check this data area for an End Job Flag. This also works for programs (RPG, Cobal, etc). This data area is not a single byte DtaAra. We store the current job info, last completed job, run time, etc ... We have a generic program that manipulates several data areas. This allows us to smoothly control the end of a CL or program. MIS
    530 pointsBadges:
    report
  • TomLiotta
    Here's a sample CL program that will end a named job if that job is currently active. It uses a CL variable with a constant value for the job-name, but it could be a parm variable or it could be retrieved from a data area or...? It is written so that it will only end the job if it is active in a specific subsystem -- QPGMR in this case. That test could be skipped or the variable holding the target subsystem name could be changed to have a different value or...? It also loops through to catch every active job with that name. It could exit when it finds the first one or it could display a message asking if the current one is the one to end or...? The example job that it ends is named DUMMYJOB and the subsystem that it targets is QPGMR. You can test it by submitting multiple jobs with that name, some to QPGMR and some to other subsystems. You can submit other jobs to QPGMR at the same time with a different job-name. (I have QPGMR set to run four concurrent jobs.) You can use something like CMD(DLYJOB 600) as the command for the submitted test job.
    pgm
    
    /* Identify a job-name and a subsystem to work over...              */
       dcl   &SCHNAME     *char   10     value( 'DUMMYJOB' )
       dcl   &SCHSBS      *char   10     value( 'QPGMR' )
    
       dcl   &SchJob      *char   26
    
    /* API User Space general error code variable... */
       dcl   &a_err       *char  128     value( x'0000008000000000' )
    
    /* Identify a *USRSPC name...                                       */
       dcl   &usrspc      *char   10     value( 'LSTACTJOBS' )
       dcl   &usrspclib   *char   10     value( 'QTEMP' )
    
       dcl   &qusrspc     *char   20
    
    /* General fields from *usrspc header...                            */
       dcl   &offslst     *int
       dcl   &nbrlste     *int
       dcl   &sizlste     *int
    
    /* Various work fields...                                           */
       dcl   &Sbs         *char   10
    
       dcl   &jobname     *char   10
       dcl   &jobusr      *char   10
       dcl   &jobnbr      *char    6
    
       dcl   &qjob        *char   26
    
    /* Various receiver variables...                                    */
       dcl   &us_hdr      *char  150
       dcl   &JOBL0100F   *char   56
       dcl   &JOBI0200F   *char   72
    
    
    /*---------------------------------------------------------------------------*/
    /* Global MONMSG...                                                          */
    /*---------------------------------------------------------------------------*/
    
       monmsg    ( cpf0000 mch0000 ) exec( goto Std_Err )
    
    
    /*                                                                           */
    /* Create *usrspc for the SBS info APIs...                                   */
    /*                                                                           */
    
       chgvar          &qusrspc               ( &usrspc *cat &usrspclib )
    
       call  QUSCRTUS         ( +
                                &qusrspc                +
                                'ACTJOB    '            +
                                x'00004000'             +
                                X'00'                   +
                                '*ALL      '            +
                      'List active jobs                                  ' +
                                '*YES      '            +
                                x'0000000000000000'     +
                              )
    
    
    /* Set the qualified search-job name...                                      */
    
       chgvar          &SchJob                ( &SCHNAME *cat '*ALL      *ALL  ' )
    
    
    /*                                                                           */
    /* List the active jobs into our *usrspc...                                  */
    /*                                                                           */
    
       call  QUSLJOB          ( +
                                &qusrspc                +
                                'JOBL0100'              +
                                &SchJob                 +
                                '*ACTIVE   '            +
                                x'0000000000000000'     +
                                '*'                     +
                                x'00000000'             +
                                x'00000000'             +
                              )
    
    
    /* Retrieve the *usrspc header...                                            */
    
       call  QUSRTVUS         ( +
                                &qusrspc                +
                                x'00000001'             +
                                x'00000096'             +
                                &us_hdr                 +
                              )
    
    /*                                                           */
    /* Get the offset to the list within the space, the number   */
    /*   of list entries and size of each entry from the header. */
    /*                                                           */
       chgvar          &offslst           %bin( &us_hdr    125 4 )
       chgvar          &nbrlste           %bin( &us_hdr    133 4 )
       chgvar          &sizlste           %bin( &us_hdr    137 4 )
    
    
    /* If no entries, then get out of here...                    */
    
       if  ( &nbrlste *eq 0 )     do
          sndpgmmsg  msgid( CPF9897 ) msgf( QCPFMSG ) +
                       msgdta( 'No active jobs found.' )
          goto   End_ActJob
       enddo
    
    
    /* Set the offset to the list within the space...            */
    
       chgvar          &offslst               ( &offslst + 1 )
    
    
    
        dowhile  ( &nbrlste *gt 0 )
    
    /*    Retrieve one listed job entry from the list...                         */
    
          call  QUSRTVUS      ( +
                                &qusrspc                +
                                &offslst                +
                                &sizlste                +
                                &JOBL0100F              +
                              )
    
    
    /* Get the qualified job name from the list entry...                         */
    
          chgvar       &qjob              %sst( &JOBL0100F  1 26 )
    
    /* Get details of that job in order to find what subsystem it's in...        */
    
          call  QUSRJOBI      ( +
                                &JOBI0200F              +
                                x'00000048'             +
                                'JOBI0200'              +
                                &qjob                   +
                                '                '      +
                              )
    
    
    /* Get the subsystem name from the receiver variable...                      */
    
          chgvar       &Sbs               %sst( &JOBI0200F 63 10 )
    
          if ( &Sbs *eq &SCHSBS )  do
    
             chgvar    &jobname           %sst( &JOBI0200F  9 10 )
             chgvar    &jobusr            %sst( &JOBI0200F 19 10 )
             chgvar    &jobnbr            %sst( &JOBI0200F 29  6 )
    
             endjob   job( &jobnbr/&jobusr/&jobname )
    
          enddo
    
          else  +
             sndpgmmsg  msgid( CPF9897 ) msgf( QCPFMSG ) +
                          msgdta( 'Found' *bcat &Sbs ) +
                          topgmq( *EXT ) msgtype( *STATUS )
    
    
    /* Bump our offset up by the size of a list entry...                         */
    
          chgvar       &offslst               ( &offslst + &sizlste )
    
    /* Decrement our loop counter and loop back if more...                       */
    
          chgvar       &nbrlste               ( &nbrlste - 1 )
    
       enddo
    
    
    End_Run:
    
       dltusrspc   &usrspclib/&usrspc  /* Cleanup */
    
       return
    
    
     Std_Err:
    
       /* Move any *DIAG messages up the stack...        */
    
       Qsys/call       QSYS/QMHMOVPM       ( +
                                             '    '          +
                                             '*DIAG     '    +
                                             x'00000001'     +
                                             '*         '    +
                                             x'00000001'     +
                                             x'00000000'     +
                                           )
       Qsys/monmsg     ( CPF0000 MCH0000 )
    
       /* Resend any *ESCAPE messages up the stack...     */
    
       Qsys/call       QSYS/QMHRSNEM       ( +
                                             '    '          +
                                             x'00000000'     +
                                           )
       Qsys/monmsg     ( CPF0000 MCH0000 )
    
       return
    
    
    endpgm
    Once you have the basics of creating a space, putting a list into it and stepping through the list, the code can be used over and over with different list APIs and with different formats. The code is written for V5R3. It can be modified for earlier releases by replacing any *INT variables with 4-byte *CHAR variables and changing out the DOWHILE for an IF/GOTO loop. It can be modernized to V5R4 and later by using various data structures instead of substringing and by using pointer logic to eliminate using the QUSRTVUS API. You should be able to compare anything in the code with the related API documentation in order to understand any piece of it. Running an actual example under debug is as good as you'll get for learning. Tom
    125,585 pointsBadges:
    report
  • TomLiotta
       if  ( &nbrlste *eq 0 )     do
          sndpgmmsg  msgid( CPF9897 ) msgf( QCPFMSG ) +
                       msgdta( ‘No active jobs found.’ )
          goto   End_ActJob
       enddo
    Minor correction -- that GOTO should be:
          goto   End_Run
    I did a little tidying up and failed to realize that I changed executeable code in addition to the comments that I changed. Be aware that this site's handling of copy/pasted program code will mess up characters such as apostrophes. Nothing I can do about that. You'll just have to change each leading and trailing quote to an apostrophe. There are one or two additional Unicode things that it messes up, and you'll want to fix those. (For example, if you type three periods as an ellipsis, it will replace them with a single ellipsis Unicode character. Messing with "code" shouldn't happen with an editor, especially within a {code} block. But, that's how it goes.) Tom
    125,585 pointsBadges:
    report
  • Jmb49
    Thank's a lot, I adapted it for V4R5 & V5R1, working very well, doing the job quickly and easy to understand. Very good work !
    10 pointsBadges:
    report

Forgot Password

No problem! Submit your e-mail address below. We'll send you an e-mail containing your password.

Your password has been sent to:

To follow this tag...

There was an error processing your information. Please try again later.

REGISTER or login:

Forgot Password?
By submitting you agree to receive email from TechTarget and its partners. If you reside outside of the United States, you consent to having your personal data transferred to and processed in the United States. Privacy

Thanks! We'll email you when relevant content is added and updated.

Following