We shut down QINTER at 3:30 AM to do a quick backup. We have 5.4. When someone leaves a terminal or PC session on with a keyboard error (last night was an "invalid F key pressed") QINTER will not go down all the way! It sits there until the session is physically terminated at the device. Anyone else see this and/or solve it?
Software/Hardware used:
iSeries or AS/400
ASKED:
December 9, 2010 3:13 PM
UPDATED:
December 12, 2010 1:47 AM
If a job in a subsystem won’t end, then you cannot end the subsystem. Subsystems will not end until all jobs in the subsystem have ended first. If you initiate ENDSBS while a job is in a state where it can’t end, then your subsystem is stuck until you can (1) get it to finish ending and (2) get the subsystem restarted. Because of that, it’s not a good idea to issue ENDSBS while jobs are still running in a subsystem.
When a job is stuck, you can try ENDJOB. After sufficient time has passed and the job has not ended, you can usually succeed with ENDJOBABN. And if that doesn’t work and you’ve already run ENDSBS, your subsystem will generally be unavailable until you can IPL the system.
Tom
LarryKat,
Here’s a thought, assuming your “quick backup” is a CL program, if you were to do a WRKACTJOB to a file, then read thru that file looking for Jobs running in QINTER, you could use ENDJOB to end each of the active jobs in QINTER. If no jobs are found running in QINTER you can continue with your “quick backup”.
We use the TAATOOL/CVTWRKACT to do WRKACTJOB to a file.
Hope this helps,
Bill Poulin
issue the commad Enddbd Qinter Option(*CNTRLD) Delay(120).
After 120 seconds any active job in the sub system will be ended and it will end.
woops that should have been endsbs(qinter) option(*Cntrld) delay(120)
Here is an example program that checks subsystem QPGMR for active jobs. If it’s all quiet, it simply returns. If *ACTIVE jobs are in there, it lists all jobs into a user space, loops through the list issuing ENDJOB for each one, then checks to see if any *ACTIVE jobs remain again.
If some haven’t ended yet, it waits 35 seconds before checking a final time. If any still remain, it sends an *ESCAPE message.
pgm /* Identify a a subsystem to work over... */ dcl &SCHSBS *char 10 value( 'QPGMR' ) dcl &SchJob *char 26 /* 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 &JobType *char 1 dcl &qjob *char 26 dcl &qSBSNam *char 20 dcl &SBSActJobs *int dcl &SBSMON *char 1 value( 'M' ) /* Sbs Monitor */ dcl &SYSJOB *char 1 value( 'S' ) /* System job */ dcl &SPLWTR *char 1 value( 'W' ) /* Spool writer */ dcl &SYSCPF *char 1 value( 'X' ) /* SCPF job */ dcl &SPLRDR *char 1 value( 'R' ) /* Spool reader */ /* Various receiver variables... */ dcl &us_hdr *char 150 dcl &JOBL0100F *char 56 dcl &JOBI0200F *char 72 dcl &rcvvar *char 76 monmsg ( cpf0000 mch0000 ) exec( goto Std_Err ) /* Check if things have ended... */ chgvar &qSBSNam ( &SCHSBS *cat '*LIBL' ) call qwdrsbsd ( + &rcvvar + x'0000004C' + 'SBSI0100' + &qSBSNam + x'00000000' + ) chgvar &SBSActJobs %bin( &rcvvar 73 4 ) /* If the the &SCHSBS has no *ACTIVE jobs, return... */ if ( &SBSActJobs *le 0 ) do sndpgmmsg msgid( CPF9897 ) msgf( QCPFMSG ) + msgdta( 'No active jobs.' ) + topgmq( *EXT ) + msgtype( *COMP ) return enddo /* */ /* Create *usrspc for the List Jobs 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 ( '*ALL *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 /* Can't actually happen... */ sndpgmmsg msgid( CPF9897 ) msgf( QCPFMSG ) + msgdta( 'No active jobs found.' ) + topgmq( *EXT ) + msgtype( *COMP ) goto End_Run 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 + ) /* Bump our offset up by the size of a list entry... */ /* Decrement our loop counter and loop back if more... */ chgvar &offslst ( &offslst + &sizlste ) chgvar &nbrlste ( &nbrlste - 1 ) /* Skip any subsystem monitor, etc., job... */ chgvar &JobType %sst( &JOBL0100F 53 1 ) if ( &JobType *eq &SBSMON *or + &JobType *eq &SYSJOB *or + &JobType *eq &SPLWTR *or + &JobType *eq &SYSCPF *or + &JobType *eq &SPLRDR ) + iterate /* 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 ) monmsg ( cpf0000 mch0000 ) sndpgmmsg msgid( CPF9897 ) msgf( QCPFMSG ) + msgdta( 'Ended' *bcat &jobname ) + topgmq( *EXT ) msgtype( *STATUS ) enddo /* This ELSE code can be removed... */ else + sndpgmmsg msgid( CPF9897 ) msgf( QCPFMSG ) + msgdta( 'Found' *bcat &Sbs ) + topgmq( *EXT ) msgtype( *STATUS ) enddo End_Run: dltusrspc &usrspclib/&usrspc /* Cleanup */ /* Check if things have ended... */ call qwdrsbsd ( + &rcvvar + x'0000004C' + 'SBSI0100' + &qSBSNam + x'00000000' + ) chgvar &SBSActJobs %bin( &rcvvar 73 4 ) /* If all *ACTIVE jobs have ended, return... */ if ( &SBSActJobs *le 0 ) do sndpgmmsg msgid( CPF9897 ) msgf( QCPFMSG ) + msgdta( 'No active jobs.' ) + topgmq( *EXT ) + msgtype( *COMP ) return enddo /* Check if things have ended... */ sndpgmmsg msgid( CPF9898 ) msgf( QCPFMSG ) + msgdta( 'Waiting 35 seconds for any jobs to end..' ) + topgmq( *EXT ) msgtype( *STATUS ) dlyjob 35 call qwdrsbsd ( + &rcvvar + x'0000004C' + 'SBSI0100' + &qSBSNam + x'00000000' + ) chgvar &SBSActJobs %bin( &rcvvar 73 4 ) /* If the the &SCHSBS still has *ACTIVE jobs...??? */ if ( &SBSActJobs *gt 0 ) do sndpgmmsg msgid( CPF9897 ) msgf( QCPFMSG ) + msgdta( 'Not all jobs ended.' ) + topgmq( *PRV ) + msgtype( *ESCAPE ) enddo 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 endpgmIt can be changed to accept a subsystem name as a parm. An ENDSBS should not be entered for the subsystem until this program returns to its caller normally.
The program is sufficient for most systems. Larger systems possibly shouldn’t use the List Job (QUSLJOB) API for this. The Open List of Jobs (QGYOLJOB) API is probably a better choice. It doesn’t use a user space, so the additional programming if all jobs can’t fit in a space wouldn’t be needed. (Not included in example.)
Also, the list could be customized to return only jobs in the chosen subsystem(s). The list in the example will include all *ACTIVE jobs in the system. A user space can hold more than a quarter million job entries, so there’s little chance of complication.
Note that it can take time to do work. Jobs might end before reaching them in the list. New jobs may start before finishing the list. That’s when it can get fun.
Tom
BTW, the program can be tested by submitting a DLYJOB 600 command to run in QPGMR. Call the program after the DLYJOB starts. The program should get to the end of the list in a couple seconds and wait until enough time has passed for the submitted job to end.
Tom