End jobs on the IBM i by User and Job Name – ENDUSRJOB

Sometimes we know the name and user of a job we might want to end, but we won’t know the job number until the job is submitted. There does not seem to be an IBM i command to end jobs when the job numbers are not known, and I have a use for one, so I built one.

To create the command, there were two options.  Use an API to list the jobs and end them, or use existing commands to find the jobs, convert a spool file to a flat file, and parse the flat file to examine the list and end the desired jobs.  I tend to prefer commands to API’s. so I went with the second option.

While I had a particular use in mind for this thing, I did decide to go ahead and make it a little more flexible, so it might be of use to more people.  I have to warn you that I did not give the thing a full QA, so it could have a bug or two in it.  I hope it is all OK, but if you see a bug, please add a comment to the post.  Also, if you use it, test it first, to make sure it does exactly what you expect it to do.

For your convenience, text files for the source have been posted here:

ENDUSRJOB

There is a command definition, a CL program, and an RPG ILE program.  The RPG program uses the RPG cycle, a program defined input file, a procedure prototype, and a line of free formatted code, so you may find it a bit stylistically eclectic.  On the other hand, it is so simple a child with a basic understanding of RPG could understand it, which is something we probably could not say if it was written with APIs, so there’s that.  Anyway, let’s take a look.

Here is the command, prompted:

endusrjob

endusrjob2

The parameters are mostly familiar from the WRKUSRJOB and ENDJOB commands.  The user is a user name, or * for current user.  Job Type is batch, interactive, or both.  The job name can be specified or left *ALL for all jobs that meet the other selection criteria.  I did add one new option to the ENDJOB option.  In addition to *CNTRLD and *IMMED, there is *ABN which will run ENDJOBABN instead of ENDJOB.

Hopefully the comments in the code explain well enough what each object does.

Here is the source for the ENDUSRJOB command:

/* The ENDUSRJOB command ends jobs with the selected option.  The      */       
/* jobs to end are selected based on User, Job Type, and Job Name.     */       
/* The WRKUSR job command is used to select jobs by User and Job Type. */       
/* The jobs selected by WRKUSRJOB are then matched to the given Job    */       
/* Name to make the final selection.  Selected jobs are ended using    */       
/* the ENDJOB command with the specified Option.                       */       
                                                                                
/* The ENDUSRJOB command is processed by CL program ENDUSRJOBC:        */       
/* CRTCMD CMD(ENDUSRJOB) PGM(ENDUSRJOBC)                               */       
                                                                                
/* This program is a demonstration.  Please test this program          */       
/* thoroughly before using it in any production setting.  It is        */       
/* provided as is.  Rod Flohr, 2014-09-11                              */       
                                                                                
             CMD        PROMPT('End User Jobs')                     
             PARM       KWD(USER) TYPE(*NAME) LEN(10) DFT(*) +                  
                          SPCVAL((*)) PROMPT('User whose jobs to end')          
             PARM       KWD(JOBTYPE) TYPE(*CHAR) LEN(12) RSTD(*YES) +           
                          DFT(*BATCH) VALUES(*BATCH *INTERACTIVE +              
                          *ALL) PROMPT('Job type')                              
             PARM       KWD(JOBNAME) TYPE(*NAME) LEN(10) DFT(*ALL) +            
                          SPCVAL((*ALL)) PROMPT('Job name')                     
             PARM       KWD(OPTION) TYPE(*CHAR) LEN(7) RSTD(*YES) +             
                          DFT(*CNTRLD) VALUES(*CNTRLD *IMMED *ABN) +            
                          PROMPT('How to end')

Here is the source for the ENDUSRJOBC program:

/* The ENDUSRJOBC program is the command processor for the ENDUSRJOB   */       
/* command.  The ENDUSRJOB command ends jobs based on selection parms. */       
/* Jobs to end are selected based on User, Job Type, and Job Name.     */       
                                                                                
/* The ENDUSRJOBC program uses the WRKUSRJOB command to pre-select     */       
/* jobs by User and Job Type. The spool file ouput is converted to a   */       
/* flat physical file for final processing by the ENDUSRJOBR program.  */       
                                                                                
/* This program is a demonstration.  Please test this program          */       
/* thoroughly before using it in any production setting.  It is        */       
/* provided as is.  Rod Flohr, 2014-09-11                              */       
                                                                                
             PGM        PARM(&USER &JOBTYPE &JOBNAME &OPTION)                   
                                                                                
             DCL        VAR(&USER) TYPE(*CHAR) LEN(10)                          
             DCL        VAR(&JOBTYPE) TYPE(*CHAR) LEN(12)                       
             DCL        VAR(&JOBNAME) TYPE(*CHAR) LEN(10)                       
             DCL        VAR(&OPTION) TYPE(*CHAR) LEN(7)                         
                                                                                
/* Find current user if passed in user is '*'.  */                              
             IF         COND(&USER = '*') THEN(RTVJOBA USER(&USER))             
                                                                                
/* Pre-select jobs by User and Job Type.  Output to spool file.  */             
             WRKUSRJOB  USER(&USER) STATUS(*ACTIVE) OUTPUT(*PRINT) +            
                          JOBTYPE(&JOBTYPE)                                     
                                                                                
/* Set up the flat physical for processing.  */                                 
             DLTF       FILE(QTEMP/DSPSBJ)                                      
             MONMSG     MSGID(CPF0000)                                          
             CRTPF      FILE(QTEMP/DSPSBJ) RCDLEN(80)                           
             CPYSPLF    FILE(QPDSPSBJ) TOFILE(QTEMP/DSPSBJ) +                   
                          SPLNBR(*LAST)                                         
             OVRDBF     FILE(DSPSBJ) TOFILE(QTEMP/DSPSBJ)                       
                                                                                
/* Call ENDUSRJOBR to finalize the selection by Job Name and */                 
/* end the selected jobs.                                    */                 
             CALL       PGM(ENDUSRJOBR) PARM(&JOBNAME &OPTION)                  
                                                                                
/* Clean up. */                                                                 
             DLTF       FILE(QTEMP/DSPSBJ)                                      
             ENDPGM

Here is the source for the ENDUSRJOBR program:

      * ENDUSRJOBR is called by ENDUSRJOBC, the command processor for the                   
      * ENDUSRJOB command.  The ENDUSRJOB command ends jobs based on selection parms.       
      * Jobs to end are selected based on User, Job Type, and Job Name.                     
                                                                                            
      * ENDUSRJOBC pre-selects active jobs by User and Job Type, using WRKUSRJOB            
      * with OUTPUT(*PRINT).  The spool file is copied to a flat file in QTEMP.             
      * The flat file is processed in this program to make the final selection for          
      * Job Name and end the selected jobs.                                                 
                                                                                            
      * This program is a demonstration.  Please test this program                          
      * thoroughly before using it in any production setting.  It is                        
      * provided as is.  Rod Flohr, 2014-09-11                                              
                                                                                            
      * Process the flat file DSPSBJ using the RPG cycle.                                   
     FDSPSBJ    IPE  F   80        DISK                                                     
                                                                                            
     DJOBID            S             28                                                     
     DCMD              S            200A                                                    
                                                                                            
      * Prototype for QCMDEXC                                                               
     D QCMDEXC         PR                  EXTPGM('QCMDEXC')                                
     D   CMD                        200A   OPTIONS(*VARSIZE) CONST                          
     D   CMDLEN                      15P 5 CONST                                            
                                                                                            
      * Input specs for flat file DSPSBJ                                                    
     IDSPSBJ    AA                                                                          
     I                                  1   80  RECORD                                      
     I                                  4   13  JOBNAME                                     
     I                                 17   26  USER                                        
     I                                 30   35  JOBNUM                                      
                                                                                            
     C     *ENTRY        PLIST                                                              
     C                   PARM                    JOBNAMEIN        10                        
     C                   PARM                    OPTION            7                        
                                                                                            
      * Only process lines with valid job numbers (skip headings, etc.)                     
     C                   IF        %CHECK('1234567890':JOBNUM) = 0              Valid JOBNUM
                                                                                            
      * Compare for selected Job Name, if not '*ALL'                                        
     C                   IF        JOBNAMEIN = JOBNAME OR JOBNAMEIN = '*ALL'    JOBNAME Match
                                                                                            
      * Format the ENDJOB command                                                           
     C                   EVAL      CMD = *BLANKS                                            
     C                   EVAL      JOBID = JOBNUM + '/' + %TRIM(USER) + '/' +               
     C                              %TRIM(JOBNAME)                                          
                                                                                            
      * If OPTION is *ABN, use ENDJOBABN, else use ENDJOB                                   
     C                   IF        OPTION = '*ABN'                              OPTION *ABN 
     C                   EVAL      CMD = 'ENDJOBABN JOB(' + %TRIM(JOBID) +                  
     C                                     ')'                                              
     C                   ELSE                                                   OPTION *ABN 
     C                   EVAL      CMD = 'ENDJOB JOB(' + %TRIM(JOBID) +                     
     C                                     ') OPTION(' + OPTION + ')'                       
     C                   ENDIF                                                  OPTION *ABN 
                                                                                            
      * Call the ENDJOB command, ignoring any errors.                                       
      /FREE                                                                                 
       CALLP(E) QCMDEXC (%TRIM(CMD) : %LEN(%TRIM(CMD)));                                    
      /END-FREE                                                                             
                                                                                            
     C                   ENDIF                                                  JOBNAME Match
                                                                                            
     C                   ENDIF                                                  Valid JOBNUM

Probably the simplest way to pick up the source is to download the ENDUSRJOB zip file linked to above. Create empty source members for each object.  Then go into Navigator, find your source members in the IFS under QSYS.LIB, right click each source member and click Edit, and then copy and paste the text for that member from the downloaded text file, and save the file.  After pasting in the text, go back to SEU or RDi and verify the source is lined up OK and compile everything.

For an example of how this might be useful, check out this post:

Can’t restart Apache on the IBM i because of zombie ZENDSVR6 jobs in QHTTPSVR

Bookmark the permalink.

One Comment

  1. Thanks very much!
    This saved me a lot of work :)

    regards,
    Martin

Leave a Reply