IBM Support

IBM i Job Termination Criteria Using SQL

How To


Summary

This document provides SQL-based approaches for ending IBM i jobs based on various criteria. These examples use the QSYS2.ACTIVE_JOB_INFO table function combined with the QSYS2.QCMDEXC to identify and terminate jobs that meet specific conditions.

Objective

Develop and demonstrate SQL-driven methods for identifying and ending IBM i jobs based on defined criteria by leveraging the QSYS2.ACTIVE_JOB_INFO table function in conjunction with QSYS2.QCMDEXC, enabling efficient job management and automation directly through SQL.

Environment

IBM i Versions 7.3 and above.

 

Steps

IBM i Job Termination Criteria Using SQL

SQL-based approaches for ending IBM i jobs based on various criteria using QSYS2.ACTIVE_JOB_INFO and QSYS2.QCMDEXC

 

Overview

This document provides SQL-based approaches for ending IBM i jobs based on various criteria. These examples use the QSYS2.ACTIVE_JOB_INFO table function combined with QSYS2.QCMDEXC to identify and terminate jobs that meet specific conditions.

Important Considerations

⚠️ Critical Warning

These queries will immediately end jobs. Always test in a non-production environment first and ensure you have proper authorization and business justification before executing.

Review the jobs that will be affected before executing the ENDJOB command

  • Consider using OPTION(*CNTRLD) instead of OPTION(*IMMED) for graceful shutdowns
  • Ensure proper logging and audit trails are in place
  • Coordinate with application owners and users before implementing automated job termination
 
Example 1: End Long-Running Batch Jobs

Use Case

Cleanup of runaway batch processes or jobs that exceed expected runtime thresholds.  This example terminates batch jobs that have been running longer than a specified duration (10 hours in this case).

 

WITH TEMPJOB (JOB_NAME, JOB_ENTERED_SYSTEM_TIME, JOB_ACTIVE_TIME, runtime_hours) AS (
    SELECT JOB_NAME,
           JOB_ENTERED_SYSTEM_TIME,
           JOB_ACTIVE_TIME,
           TIMESTAMPDIFF(8, CAST(CURRENT TIMESTAMP - JOB_ENTERED_SYSTEM_TIME AS CHAR(22))) AS runtime_hours
    FROM TABLE (
        QSYS2.ACTIVE_JOB_INFO(DETAILED_INFO => 'WORK')
    ) AS X
    WHERE SUBSYSTEM LIKE 'QBATCH'  -- Target batch subsystem
      AND JOB_TYPE <> 'SBS'        -- Exclude subsystem monitor jobs
      AND JOB_ACTIVE_TIME + 10 HOURS < CURRENT_TIMESTAMP  -- Jobs running > 10 hours
)
SELECT JOB_NAME,
       JOB_ENTERED_SYSTEM_TIME,
       JOB_ACTIVE_TIME,
       runtime_hours,
       QSYS2.QCMDEXC('ENDJOB JOB(' || JOB_NAME || ') OPTION(*IMMED) LOGLMT(0)') AS "Success?"
FROM TEMPJOB;
 

Key Parameters:

  • SUBSYSTEM LIKE 'QBATCH': Targets jobs in the batch subsystem
  • JOB_ACTIVE_TIME + 10 HOURS: Adjustable threshold for maximum runtime
  • OPTION(*IMMED): Immediate termination (use *CNTRLD for controlled)
  • LOGLMT(0): Prevents excessive logging during job end, if a Joblog is required, remove this parameter from the command.
 
Example 2: After-Hours Cleanup of Interactive Sessions

Use Case

Automatic cleanup of user sessions left open after the workday ends.  This example ends interactive jobs after business hours to free system resources.

 

WITH TEMPJOB (JOB_NAME, JOB_ENTERED_SYSTEM_TIME, JOB_ACTIVE_TIME, runtime_hours) AS (
    SELECT JOB_NAME,
           JOB_ENTERED_SYSTEM_TIME,
           JOB_ACTIVE_TIME,
           TIMESTAMPDIFF(8, CAST(CURRENT TIMESTAMP - JOB_ENTERED_SYSTEM_TIME AS CHAR(22))) AS runtime_hours
    FROM TABLE (
        QSYS2.ACTIVE_JOB_INFO(DETAILED_INFO => 'WORK')
    ) AS X
    WHERE SUBSYSTEM LIKE 'QINTER'  -- Target interactive subsystem
      AND JOB_TYPE <> 'SBS'        -- Exclude subsystem monitor jobs
      AND CURRENT_TIME > '17:00'   -- End jobs after 5:00 PM
)
SELECT JOB_NAME,
       JOB_ENTERED_SYSTEM_TIME,
       JOB_ACTIVE_TIME,
       runtime_hours,
       QSYS2.QCMDEXC('ENDJOB JOB(' || JOB_NAME || ') OPTION(*IMMED) LOGLMT(0)') AS "Success?"
FROM TEMPJOB;

 

Key Parameters:

  • SUBSYSTEM LIKE 'QINTER': Targets interactive jobs
  • CURRENT_TIME > '17:00': Time-based trigger (adjust for your business hours)
  • Consider adding exceptions for specific users or job names if needed
  • LOGLMT(0): Prevents excessive logging during job end, if a Joblog is required, remove this parameter from the command.
 
Example 3: End Display Wait (DSPW) Jobs After Hours

Use Case

Cleanup of idle interactive sessions that are waiting for user input but left unattended.  This example targets interactive jobs stuck in display wait status after business hours.

 

WITH TEMPJOB (JOB_NAME, JOB_ENTERED_SYSTEM_TIME, JOB_ACTIVE_TIME, JOB_STATUS, runtime_hours) AS (
    SELECT JOB_NAME,
           JOB_ENTERED_SYSTEM_TIME,
           JOB_ACTIVE_TIME,
           JOB_STATUS,
           TIMESTAMPDIFF(8, CAST(CURRENT TIMESTAMP - JOB_ENTERED_SYSTEM_TIME AS CHAR(22))) AS runtime_hours
    FROM TABLE (
        QSYS2.ACTIVE_JOB_INFO(DETAILED_INFO => 'WORK')
    ) AS X
    WHERE SUBSYSTEM LIKE 'QINTER'  -- Target interactive subsystem
      AND JOB_TYPE <> 'SBS'        -- Exclude subsystem monitor jobs
      AND JOB_STATUS = 'DSPW'      -- Display wait status
      AND CURRENT_TIME > '17:00'   -- After 5:00 PM
)
SELECT JOB_NAME,
       JOB_ENTERED_SYSTEM_TIME,
       JOB_ACTIVE_TIME,
       JOB_STATUS,
       runtime_hours,
       QSYS2.QCMDEXC('ENDJOB JOB(' || JOB_NAME || ') OPTION(*IMMED) LOGLMT(0)') AS "Success?"
FROM TEMPJOB;
 
 

Key Parameters:

  • JOB_STATUS = 'DSPW': Specifically targets jobs in display wait
  • Combines time-based and status-based criteria for precise targeting
  • Useful for freeing up interactive job slots
  • LOGLMT(0): Prevents excessive logging during job end, if a Joblog is required, remove this parameter from the command.
 
Example 4: End Jobs by Specific User Profile

Use Case

Immediate termination of all sessions for a compromised or terminated user account. This example terminates all active jobs for a specific user profile, useful for security incidents or account deactivation.

 

WITH TEMPJOB (JOB_NAME, JOB_USER, JOB_ENTERED_SYSTEM_TIME, JOB_ACTIVE_TIME, SUBSYSTEM) AS (
    SELECT JOB_NAME,
           JOB_USER,
           JOB_ENTERED_SYSTEM_TIME,
           JOB_ACTIVE_TIME,
           SUBSYSTEM
    FROM TABLE (
        QSYS2.ACTIVE_JOB_INFO(DETAILED_INFO => 'WORK')
    ) AS X
    WHERE JOB_USER = 'USERID'     -- Specify the user profile
      AND JOB_TYPE <> 'SBS'       -- Exclude subsystem monitor jobs
      AND JOB_NAME NOT LIKE 'QZDA%'  -- Exclude system jobs if needed
)
SELECT JOB_NAME,
       JOB_USER,
       JOB_ENTERED_SYSTEM_TIME,
       JOB_ACTIVE_TIME,
       SUBSYSTEM,
       QSYS2.QCMDEXC('ENDJOB JOB(' || JOB_NAME || ') OPTION(*IMMED) LOGLMT(0)') AS "Success?"
FROM TEMPJOB;

 

Key Parameters:

  • JOB_USER = 'USERID': Replace with the target user profile
  • Terminates jobs across all subsystems for the specified user
  • Consider security implications and proper authorization
  • LOGLMT(0): Prevents excessive logging during job end, if a Joblog is required, remove this parameter from the command.
 
Example 5: End Jobs Consuming Excessive CPU

Use Case

Identify and terminate resource-intensive jobs that may be impacting system performance. This example targets jobs that are consuming high CPU resources for an extended period.

 

WITH TEMPJOB (JOB_NAME, JOB_USER, SUBSYSTEM, CPU_TIME, ELAPSED_CPU_PERCENTAGE, runtime_hours) AS (
    SELECT JOB_NAME,
           JOB_USER,
           SUBSYSTEM,
           CPU_TIME,
           ELAPSED_CPU_PERCENTAGE,
           TIMESTAMPDIFF(8, CAST(CURRENT TIMESTAMP - JOB_ENTERED_SYSTEM_TIME AS CHAR(22))) AS runtime_hours
    FROM TABLE (
        QSYS2.ACTIVE_JOB_INFO(DETAILED_INFO => 'ALL')
    ) AS X
    WHERE JOB_TYPE <> 'SBS'                    -- Exclude subsystem monitor jobs
      AND ELAPSED_CPU_PERCENTAGE > 50          -- Jobs using > 50% CPU
      AND CPU_TIME > 300000                    -- CPU time > 300 seconds (5 minutes)
      AND JOB_ACTIVE_TIME + 1 HOURS < CURRENT_TIMESTAMP  -- Running > 1 hour
)
SELECT JOB_NAME,
       JOB_USER,
       SUBSYSTEM,
       CPU_TIME,
       ELAPSED_CPU_PERCENTAGE,
       runtime_hours,
       QSYS2.QCMDEXC('ENDJOB JOB(' || JOB_NAME || ') OPTION(*IMMED) LOGLMT(0)') AS "Success?"
FROM TEMPJOB;

 

Key Parameters:

  • ELAPSED_CPU_PERCENTAGE > 50: Targets jobs using more than 50% CPU
  • CPU_TIME > 300000: Minimum CPU time threshold (in milliseconds)
  • DETAILED_INFO => 'ALL': Required to access CPU metrics
  • Adjust thresholds based on your system's normal workload patterns
  • LOGLMT(0): Prevents excessive logging during job end, if a Joblog is required, remove this parameter from the command.

 

Best Practices

Testing and Validation

1. Preview Before Execution

Remove the QSYS2.QCMDEXC call to preview which jobs would be affected:

SELECT JOB_NAME, JOB_USER, SUBSYSTEM, runtime_hours FROM TEMPJOB;
 

2. Start with Controlled Shutdown

Use OPTION(*CNTRLD) instead of OPTION(*IMMED) for initial testing:

QSYS2.QCMDEXC('ENDJOB JOB(' || JOB_NAME || ') OPTION(*CNTRLD) DELAY(30)')

 

3. Add Exclusions

Protect critical jobs by adding exclusion criteria:

AND JOB_NAME NOT LIKE 'CRITICAL%' AND JOB_USER NOT IN ('QSECOFR', 'ADMIN')
 

 

Scheduling and Automation

  • Schedule these queries during maintenance windows when appropriate
  • Implement notification mechanisms before automated job termination
  • Maintain audit logs of all automated job terminations
  • Document business rules and approval processes

Error Handling

  • Monitor the "Success?" column for failed termination attempts
  • Investigate jobs that cannot be ended (may indicate system issues)
  • Implement retry logic for jobs that fail to terminate

 

Scheduling with Job Scheduler (ADDJOBSCDE)

To automate these job termination queries, you can schedule them using the IBM i Job Scheduler with the RUNSQLSTM command. This allows you to run SQL scripts at specific times or intervals.

Step 1: Create SQL Script Files

First, save your SQL query to a source physical file member. For example, to create a script for ending long-running batch jobs:

CRTSRCPF FILE(QGPL/SQLSCRIPTS) RCDLEN(112) ADDPFM FILE(QGPL/SQLSCRIPTS) MBR(ENDBATCH) TEXT('End long-running batch jobs')

Then edit the member (using STRSEU or EDTF) and add your SQL.

 

Step 2: Test the SQL Script

Before scheduling, test the script manually using RUNSQLSTM:

RUNSQLSTM SRCFILE(QGPL/SQLSCRIPTS) SRCMBR(ENDBATCH) COMMIT(*NONE) NAMING(*SQL)

 

Step 3: Schedule with ADDJOBSCDE

Once tested, schedule the script to run automatically using ADDJOBSCDE:

 

Example 1: Daily Execution at Specific Time

End long-running batch jobs daily at 11:00 PM:

ADDJOBSCDE JOB(ENDBATCH) CMD(RUNSQLSTM SRCFILE(QGPL/SQLSCRIPTS) SRCMBR(ENDBATCH) COMMIT(*NONE) NAMING(*SQL)) FRQ(*WEEKLY) SCDDATE(*NONE) SCDDAY(*ALL) SCDTIME(230000) TEXT('End long-running batch jobs')
 

 

Example 2: After-Hours Interactive Cleanup

End interactive sessions after business hours (5:30 PM) on weekdays:

ADDJOBSCDE JOB(ENDINTER) CMD(RUNSQLSTM SRCFILE(QGPL/SQLSCRIPTS) SRCMBR(ENDINTER) COMMIT(*NONE) NAMING(*SQL)) FRQ(*WEEKLY) SCDDATE(*NONE) SCDDAY(*MON *TUE *WED *THU *FRI) SCDTIME(173000) TEXT('End interactive sessions after hours')
 

 

Managing Scheduled Jobs

View scheduled jobs:

WRKJOBSCDE
 

Or using SQL:

SELECT JOB_NAME, SCHEDULED_DATE, SCHEDULED_TIME, SCHEDULED_DAY, FREQUENCY, STATUS, TEXT_DESCRIPTION FROM QSYS2.SCHEDULED_JOB_INFO WHERE JOB_NAME IN ('ENDBATCH', 'ENDINTER', 'ENDCPU') ORDER BY JOB_NAME;

 

Remove a scheduled job:

RMVJOBSCDE JOB(ENDBATCH)
 

Change schedule:

CHGJOBSCDE JOB(ENDBATCH) SCDTIME(220000)

 

Hold/Release a scheduled job:

HLDJOBSCDE JOB(ENDBATCH) RLSJOBSCDE JOB(ENDBATCH)
 

 

Best Practices for Scheduled Job Termination

  1. Start with Logging Only: Initially schedule queries without QCMDEXC to log results only
  2. Gradual Implementation: Begin with conservative thresholds and adjust based on results
  3. Regular Review: Periodically review job logs to ensure proper operation
  4. Error Handling: Monitor for failed executions and investigate causes
  5. Documentation: Maintain records of scheduled jobs and their business justification

 

Additional Resources

 

Conclusion

These SQL-based job termination techniques provide powerful tools for system administrators to manage IBM i workloads effectively. Always exercise caution, test thoroughly, and ensure proper authorization before implementing automated job termination procedures.

Remember

The key to successful automated job management is careful planning, thorough testing, and continuous monitoring. Start conservatively and adjust based on your specific environment and requirements. Always test in non-production environments first.

Document Location

Worldwide

[{"Type":"MASTER","Line of Business":{"code":"LOB68","label":"Power HW"},"Business Unit":{"code":"BU070","label":"IBM Infrastructure"},"Product":{"code":"SWG60","label":"IBM i"},"ARM Category":[{"code":"a8mgJ00000005kTQAQ","label":"IBM i-\u003EWork Management"}],"ARM Case Number":"","Platform":[{"code":"PF012","label":"IBM i"}],"Version":"7.3.0;7.4.0;7.5.0;7.6.0"}]

Document Information

Modified date:
28 May 2026

UID

ibm17274186