如何檢核某 Job 有含所指定的 MSGID, 並取得該訊息的(MSGDTA)欄位資料(Command CHKJLMSGID)?
先前有 Commamd CHKJOBLOG(利用 QMHLJOBL List Job Log API)來檢核 joblog,並將該訊息傳送到指定的 MSGQ,
此次以 QGYOLJBL Open list of joblog messages API 來檢核所指定的 MSGID是否存在,並回傳該訊息相關資訊是否空白來確認 MSGID 是否存在?
空白表不存在。
File : QRPGLESRC
Member: CHKJLMSGID
Type : RPGLE
OS version: V5R1 以上
Usage : CRTBNDRPG CHKJLMSGID TGTRLS(V5R1M0)
**
** Program . . : CHKJLMSGID
** Description : Check Joblog by MsgId
** Author . . : Vengoal Chang
** Published . : Dimerco Data System Corporation
** Date . . . : July 1, 2009
**
**
** Program summary
** ---------------
**
** Message handling API:
** QGYOLJBL Open list of joblog Lists messages from the specified
** messages job's joblog in sending data and
** time order. Replies to inquiry-
** messages are listed immediately
** after the message it is associated
** with.
**
** The QGYOLJBL API is found in the
** QGY library as are all other open
** list APIs - prior to V5R3.
**
** To retrieve open lists entries
** from an already open list the
** QGYGTLE (Get List Entries) API
** is available.
**
** Open list APIs:
** QGYGTLE Get list entries To retrieve open lists entries
** from an already open list the
** QGYGTLE (Get List Entries) API
** is available.
**
** QGYCLST Close list This API closes the previously
** opened list identified by the
** request handle parameter.
** Storage allocated is freed.
**
** Sequence of events:
** 1. The API input parameters are initialized
**
** 2. The open list of joblog messages API is called
**
** 3. If an error occurred calling the API or
** no entry is found blanks are returned to
** the caller
**
** 4. The most recent secified message id joblog message
** data is retrieved and returned to the caller.
**
**
** Parameters:
** PxJobId INPUT Qualified job name of the job whose joblog
** messages are to be listed. The following
** format applies:
**
** 1-10 Char 10 Job name
** 11-20 Char 10 Job user
** 21-26 Char 6 Job number
**
** The special value '*' is allowed. This value
** identifies the current job.
**
** PxMsgF OUTPUT The MSGF of the most recent found msgid
** is returned. If no msgid found blanks
** are returned.
**
** PxMsgFLib OUTPUT The MSGFLIB of the most recent found msgid
** is returned. If no msgid found blanks
** are returned.
**
** PxMsgDta OUTPUT The MSGDTA of the most recent found msgid
** is returned. If no msgid found blanks
** are returned.
**
**
** Programmer's note:
** As mentioned above library QGY must be in the job library list
** to succesfully run this program on releases prior to V5R3.
**
** To list another user's joblog *JOBCTL special authority is
** required.
**
** To list the joblog of a user having user class *SECOFR, special
** authority *ALLOBJ is required.
**
**
** Compile options:
**
** CrtRpgMod Module( CHKJLMSGID )
**
** CrtPgm Srvpgm( CHKJLMSGID )
** Module( CHKJLMSGID )
** ActGrp( QILE )
**
**
**-- Control spec: -----------------------------------------------------**
H Option( *SrcStmt ) DftActGrp(*NO)
**-- API error data structure: -----------------------------------------**
D ERRC0100 Ds Qualified
D BytPrv 10i 0 Inz( %Size( ERRC0100 ))
D BytAvl 10i 0
D MsgId 7a
D 1a
D MsgDta 128a
**-- API parameters: ---------------------------------------------------**
D RtnRcdNbr s 10i 0
**
D SltInf Ds Qualified
D RtvDrc 10a
D JobId 26a Inz( '*' )
D IntJobId 16a
D StrKey 4a
D MsgLenMax 10i 0 Inz( -1 )
D HlpLenMax 10i 0 Inz( 0 )
D FldIdsOfs 10i 0 Inz( 84 )
D FldIdsNbr 10i 0 Inz( %Elem( SltInf.FldIds ))
D CalMsqOfs 10i 0 Inz( 88 )
D CalMsqLen 10i 0 Inz( 1 )
D 4a
D FldIds 10i 0 Dim( 1 ) Inz( 201 )
D CalMsq 10a Inz( '*' )
**
D LstInf Ds Qualified
D RcdNbrTot 10i 0
D RcdNbrRtn 10i 0
D Handle 4a
D RcdLen 10i 0
D InfSts 1a
D TimStp 13a
D LstSts 1a
D 1a
D InfLen 10i 0
D Rcd1 10i 0
D 40a
**
D OLJL0100 Ds 32767 Qualified
D NxtMsgOfs 10i 0
D FldDtaOfs 10i 0
D FldNbrOfs 10i 0
D MsgSev 10i 0
D MsgId 7a
D MsgTyp 2a
D MsgKey 4a
D MsgF 10a
D MsgFlib 10a
D DatSnt 7a
D TimSnt 6a
D MicSec 6a
**
D FldDta Ds Qualified Based( pFldDta )
D NxtFldOfs 10i 0
D FldDtaLen 10i 0
D FldId 10i 0
D DtaTyp 1a
D DtaSts 1a
D 14a
D DtaLen 10i 0
D Dta 1024a
**-- Open list of job log messages:
D LstLogMsg Pr ExtPgm( 'QGYOLJBL' )
D LlRcvVar 65535a Options( *VarSize )
D LlRcvVarLen 10i 0 Const
D LlLstInf 80a
D LlNbrRcdRtn 10i 0 Const
D LlLogSltInf 1024a Const Options( *VarSize )
D LlLogSltLen 10i 0 Const
D LlError 1024a Options( *VarSize )
**-- Get list entry:
D GetLstEnt Pr ExtPgm( 'QGYGTLE' )
D GlRcvVar 65535a Options( *VarSize )
D GlRcvVarLen 10i 0 Const
D GlHandle 4a Const
D GlLstInf 80a
D GlNbrRcdRtn 10i 0 Const
D GlRtnRcdNbr 10i 0 Const
D GlError 1024a Options( *VarSize )
**-- Close list:
D CloseLst Pr ExtPgm( 'QGYCLST' )
D ClHandle 4a Const
D ClError 1024a Options( *VarSize )
D CmdStr S 1024 INZ
D CmdLen S 15P 5 INZ(1024)
**-- Call system command:
D QCMDEXC PR ExtPgm('QCMDEXC')
D Cmd 500A options(*varsize) Const
D CmdLen 15P 5 Const
D CHKJLMSGID Pr
D PxJobId 26a
D PxMsgId 7a
D PxMsgF 10a
D PxMsgFLib 10a
D PxMsgDta 256a
**
D CHKJLMSGID Pi
D PxJobId 26a
D PxMsgId 7a
D PxMsgF 10a
D PxMsgFLib 10a
D PxMsgDta 256a
/Free
CmdStr = 'ADDLIBLE QGY' ;
CmdLen = %len(%trim(CmdStr));
Monitor;
QCMDEXC(%trim(CmdStr) : CmdLen);
On-Error;
EndMon;
PxMsgF = *Blanks;
PxMsgFLib = *Blanks;
PxMsgDta = *Blanks;
SltInf.JobId = PxJobId;
SltInf.RtvDrc = '*PRV';
SltInf.StrKey = x'FFFFFFFF';
LstLogMsg( OLJL0100
: %Size( OLJL0100 )
: LstInf
: 1
: SltInf
: %Size( SltInf )
: ERRC0100
);
If ERRC0100.BytAvl = *Zero;
DoW LstInf.LstSts <> '2' Or LstInf.RcdNbrTot >= RtnRcdNbr;
pFldDta = %Addr( OLJL0100 ) + OLJL0100.FldDtaOfs;
If OLJL0100.MsgId = PxMsgId ;
PxMsgF = OLJL0100.MsgF;
PxMsgFLib= OLJL0100.MsgFLib;
PxMsgDta = %Subst( FldDta.Dta: 1: FldDta.DtaLen );
Leave;
EndIf;
RtnRcdNbr += 1;
GetLstEnt( OLJL0100
: %Size( OLJL0100 )
: LstInf.Handle
: LstInf
: 1
: RtnRcdNbr
: ERRC0100
);
If ERRC0100.BytAvl > *Zero;
Leave;
EndIf;
EndDo;
CloseLst( LstInf.Handle: ERRC0100 );
EndIf;
*InLr = *On;
Return;
/End-Free
File : QCMDSRC
Member: CHKJLMSGID
Type : CMD
Usage : CRTCMD CHKJLMSGID ALLOW(*IPGM *BPGM)
/********************************************************************/
/* Title: CHKJLMSGID: Check JobLog by MsgId */
/* */
/* Description - This command performs job log checked by MSGID */
/* */
/* The Create Command command should include the following: */
/* */
/* CRTCMD CMD(CHKJLMSGID) PGM(CHKJLMSGID) */
/* */
/********************************************************************/
/*------------------------------------------------*/
/* Command Definition */
/*------------------------------------------------*/
CMD PROMPT('Check JobLog by MsgID')
PARM KWD(JOB) +
TYPE(Q10DD) +
DFT(*) +
SNGVAL( +
(* )) +
KEYPARM(*YES) +
PROMPT('Job name' 1)
PARM KWD(MSGID) TYPE(*CHAR) LEN(7) SPCVAL((*ALL)) +
MIN(1) PROMPT('Message ID to be checked')
PARM KWD(MSGF) TYPE(*CHAR) LEN(10) +
RTNVAL(*YES) PROMPT('CL var for +
MSGF (10)')
PARM KWD(MSGFLIB) TYPE(*CHAR) LEN(10) +
RTNVAL(*YES) PROMPT('CL var for +
MSGFLIB (10)')
PARM KWD(MSGDTA) TYPE(*CHAR) LEN(256) +
RTNVAL(*YES) PROMPT('CL var for +
MSGDTA (256)')
Q10DD: QUAL TYPE(*NAME) +
LEN(10) +
MIN(1) +
EXPR(*YES)
QUAL TYPE(*NAME) +
LEN(10) +
EXPR(*YES) +
PROMPT('User')
QUAL TYPE(*CHAR) +
LEN(6) +
RANGE( +
'000000' +
'999999') +
FULL(*YES) +
EXPR(*YES) +
PROMPT('Number')
File : QCLSRC
Member: CHKJLMSGT
Type : CLP
Usage : CRTCLPGM CHKJLMSGT
Testing sample source
PGM
DCL &MSGF *CHAR 10
DCL &MSGFLIB *CHAR 10
DCL &MSGDTA *CHAR 256
DCL &MSGID *CHAR 7
DCL &MSGTXT *CHAR 256
CHGVAR &MSGID 'CPIAD02'
CHKJLMSGID JOB(291419/QUSER/QZDASOINIT) MSGID(&MSGID) +
MSGF(&MSGF) MSGFLIB(&MSGFLIB) MSGDTA(&MSGDTA)
IF (&MSGF *NE ' ' ) DO
SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +
MSGDTA(&MSGDTA)
ENDDO
CHGVAR &MSGID 'AMQ7163'
CHKJLMSGID JOB(295970/QMQM/AMQZLAA0) MSGID(&MSGID) +
MSGF(&MSGF) MSGFLIB(&MSGFLIB) MSGDTA(&MSGDTA)
IF (&MSGF *NE ' ' ) DO
SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +
MSGDTA(&MSGDTA)
RTVMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +
MSGDTA(&MSGDTA) MSG(&MSGTXT)
SNDPGMMSG MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA(&MSGTXT)
ENDDO
CHGVAR &MSGID 'CPC1221'
CHKJLMSGID JOB(288243/FUND/TRI603Q2) MSGID(&MSGID) +
MSGF(&MSGF) MSGFLIB(&MSGFLIB) MSGDTA(&MSGDTA)
IF (&MSGF *NE ' ' ) DO
SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +
MSGDTA(&MSGDTA)
ENDDO
ENDPGM
A blog about IBM i (AS/400), MQ and other things developers or Admins need to know.
星期三, 11月 08, 2023
2009-07-01 如何檢核某 Job 有含所指定的 MSGID, 並取得該訊息的(MSGDTA)欄位資料(Command CHKJLMSGID)?
2008-05-16 如何取得 Job 狀態為 MSGW 的程式錯誤訊息,並傳送程式錯誤訊息給指定使用者?(Command RTVMSGWJL with API QMHLJOBL)
如何取得 Job 狀態為 MSGW 的程式錯誤訊息,並傳送程式錯誤訊息給指定使用者?(Command RTVMSGWJL with API QMHLJOBL)
你可以先使用 API QUSLJOB 取得所有 Job 的列表,再篩選 Job 狀態為 MSGW 的 Job 執行 RTVMSGWJL 指令即可。
File : QRPGLESRC
Member : RTVMSGWJLR
Type : RPGLE
Usage : CRTBNDCL PGM(RTVMSGWJL)
OS Version: V5R1 以上
H DFTACTGRP(*NO) ACTGRP(*CALLER) BNDDIR('QC2LE') EXPROPTS(*RESDECPOS)
H DATFMT(*ISO) TIMFMT(*ISO) DEBUG
H OPTION(*SRCSTMT:*NODEBUGIO)
*----------------------------------------------------------------
* RTVMSGWJL Retrieve Job MSGW ErrMsg from Job Log
* Copyright (C) 04/03/2008 Vengoal Chang
* This program is free software, you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation.
*
*----------------------------------------------------------------
* This program retrieve specified job job's log and send err log
* to specified MSGQ, you could modify for checking message
* type or message id as your request.
*----------------------------------------------------------------
* api (application program interfaces) used:
* quscrtus create user space
* qusptrus retrieve pointer to user space
* qmhljobl list job log messages
* qezsndmg send message to user
*----------------------------------------------------------------
D uSpaceName s 20 inz('RTVMSGWJL QTEMP ')
D msgtxt s 768
D msgtxt494 s 494
D msgtxt06 s 256
D msgtxt15 s 256
D msgtxt17 s 256
D QUSLIB s 10
D MsgQDs Ds
D MsgQEntSize 4B 0
D MsgQEntStr 20 Dim( 20 )
D Idx S 2 0
D AryIdx S 10I 0
D QualMsgq DS
D MsgQ 10
D MsgQLib 10
*Array for contain MsgQStr
D MsgQUsrDs Ds
D MsgQUsrAry 10 Dim( 20 )
D Inz( *HiVal ) Ascend
* -------------------------------------------------------------------
* - User space attributes data structure -
* -------------------------------------------------------------------
D QUSAttr DS
D QUSNumRec 10I 0 Inz( 1 )
D QUSKey 10I 0 Inz( 3 )
D QUSRecLen 10I 0 Inz( 1 )
D QUSRecData 1A Inz( '1' )
*----------------------------------------------------------------
* Get user space list info from header section.
*----------------------------------------------------------------
D ds based(uHeadPtr)
D uOffSetToList 125 128i 0
D uNumOfEntrys 133 136i 0
D uSizeOfEntry 137 140i 0
*
D uListEntry1 ds Based(uListPtr )
D uOffsetToNext 10i 0 overlay(uListEntry1:1)
D uOffsetToFlds 10i 0 overlay(uListEntry1:5)
D uNumFldsRetrnd 10i 0 overlay(uListEntry1:9)
D uMsgSeverity 10i 0 overlay(uListEntry1:12)
D uMsgId 7a overlay(uListEntry1:17)
D uMsgType 2a overlay(uListEntry1:24)
D uMsgKey 4a overlay(uListEntry1:26)
D uMsgFile 20a overlay(uListEntry1:30)
D uMsgFileName 10a overlay(uListEntry1:30)
D uMsgFileLib 10a overlay(uListEntry1:40)
* these fields repeat for each key selected.
D uListEntry2 ds Based(uListPtr2)
D u2OffsetToNext 10i 0
D u2LengthOfFlds 10i 0
D u2IdentifierF 10i 0
D u2TypeOfData 1a
D u2StatOfData 1a
D u2Reserved 14a
D u2LengthOfData 10i 0
D u2Data 500
*----------------------------------------------------------------
* Error return code parm for APIs.
*----------------------------------------------------------------
D vApiErrDs ds
D vbytpv 10i 0 inz(%size(vApiErrDs))
D vbytav 10i 0 inz(0)
D vmsgid 7a
D vresvd 1a
D vrpldta 50a
*
*----------------------------------------------------------------
* Message selection data structure.
*
* Retrieve JOB Log direction
*-----------------------------|-------------|--------------------
* Parameter | From Top | From Bottom
*-----------------------------|-------------|--------------------
* msListDirection | *NEXT | *PRV
* msStartingMessageKey | X'00000000' | X'FFFFFFFF'
*----------------------------------------------------------------
D MsgSelectDS ds
D msMaxMsgRequested...
D 10i 0 inz(-1) overlay(msgSelectDS:1) num of msg requested
D msListDirection...
D 10a inz('*NEXT') overlay(msgSelectDS:5) List direction
D msQualifiedJobName...
D 10a inz('*') overlay(msgSelectDS:15) * = current job
D msQualifiedUserName...
D 10a inz(' ') overlay(msgSelectDS:25) = current job
D msQualifiedJobNumber...
D 6a inz(' ') overlay(msgSelectDS:35) = current job
D msInternalJobIdentifier...
D 16a inz(' ') overlay(msgSelectDS:41) = current job
D msStartingMessageKey...
D 4a inz(x'00000000') start newest message
D overlay(msgselectDS:57)
D msMaxMsgLength...
D 10i 0 inz(500) overlay(msgSelectDS:61) id 301,302 lengths
D msMaxMsgHelpLength...
D 10i 0 inz(100) overlay(msgSelectDS:65) id 401,402,403,404
D msOffsetToIdentifiersOfFieldstoReturn...
D 10i 0 inz(84) overlay(msgSelectDS:69) to start of array
D msNumberOfFieldsToReturn...
D 10i 0 inz(1) overlay(msgSelectDS:73)
D msOffsetToCallMsgQname...
D 10i 0 inz(88) overlay(msgSelectDS:77)
D msLengthOfCallMsgQname...
D 10i 0 inz(1) overlay(msgSelectDS:81)
D msIndentifiersOfFieldsToReturn...
D 10i 0 inz(0302) overlay(msgSelectDS:85)
D msCallMessageQueueName...
D 1a inz('*') overlay(msgSelectDS:89)
*----------------------------------------------------------------
* Create Prototypes for calls
* --------------------------------------------------------------------
* - QusCrtUs - Create User Space API -
* - -
* - Usage Length Type Parameter Description -
* - -
* - Input 20 Character Qualified user space name -
* - Input 10 Character Extended attribute -
* - Input 4 0 Binary Initial size -
* - Input 1 Character Initial value -
* - Input 10 Character Public authority -
* - Input 50 Character Text description -
* - Replace 10 Character Replace -
* --------------------------------------------------------------------
D quscrtus PR ExtPgm('QUSCRTUS')
D 20
D 10 const
D 10i 0 const
D 1 const
D 10 const
D 50 const
D 10 const
Db like(vApiErrDS)
* -------------------------------------------------------------------
* - Qusptrus - Get user space pointer API -
* - -
* - Usage Length Type Parameter Description -
* - -
* - Input 20 Character Qualified user space name -
* - Output * Pointer UserSpace Pointer -
* - Output Error Code -
* - -----------------------------------------------------------------
D qusptrus PR ExtPgm('QUSPTRUS') retrieve pointer
D 20 Space Name
D * pointer
Db like(vApiErrDS) error parm
* -------------------------------------------------------------------
* - Quscusat - Change User Space Attributes API -
* - -
* - Usage Length Type Parameter Description -
* - -
* - Output 10 Character Returned library -
* - Input 20 Character Qualified user space name -
* - Input 13 Character Attribute structure -
* - Output Error code -
* -------------------------------------------------------------------
D quscusat PR ExtPgm( 'QUSCUSAT' )
D 10A Const
D 20A Const
D 13A Const
Db like(vApiErrDS)
* ---------------------------------------------------------------
D system PR 10I 0 extproc('system')
D i_cmd * value options(*string)
*
D EXCP_MSGID S 7A import('_EXCP_MSGID')
* --------------------------------------------------------------
D qmhljobl PR ExtPgm('QMHLJOBL ')
D 20
D 8 const
Db like(MsgSelectDS)
D 10i 0 const
D 8 const
Db like(vApiErrDS)
* --------------------------------------------------------------
D qmhsndm PR ExtPgm('QMHSNDM')
D msgid 7 const
D msgfil 20 const
D msgtxt 256 const
D msglen 10i 0 const
D msgtype 10 const
D msgq 10 const
D msgq# 10i 0 const
D rpymq 20 const
D msgkey 4 const
Db like(vApiErrDS)
* --------------------------------------------------------------
D QEZSNDMG PR ExtPgm('QEZSNDMG')
D Msgtype 10A const
D DelivMode 10A const
D MsgTxt 32767A const options(*varsize)
D MsgLen 10I 0 const
D MsgQ 10A const
D dim(32767) options(*varsize)
D NumMsgQ 10I 0 const
D MsgSent 10I 0
D FuncReq 10I 0
D ErrorCode 32767A options(*varsize)
D DspScrn 1A const options(*nopass)
D ReplyQ 20A const options(*nopass)
D NameType 4A const options(*nopass)
D CCSID 10I 0 const options(*nopass)
D ErrorCode DS
D BytesProv 10I 0 inz(0)
D BytesAvail 10I 0 inz(0)
D msgTypeA s 10
D sentcode s 10I 0
D funccode s 10I 0
D main PR extpgm('RTVMSGWJLR')
D jobname 10
D jobuser 10
D jobnumber 6
D msgtype 5
D msgQDsInput like(MsgQDs)
D main PI
D jobname 10
D jobuser 10
D jobnumber 6
D msgtype 5
D msgQDsInput like(MsgQDs)
*----------------------------------------------------------------
* Main Process
*----------------------------------------------------------------
C eval *inlr = *on
C eval msQualifiedJobName = jobname
C eval msQualifiedUserName = jobuser
C eval msQualifiedJobNumber = jobnumber
c eval msgTypeA = MsgType
C eval msgQDs = msgQDsInput
C Eval Idx = 0
C Eval AryIdx = 0
C DoW Idx < MsgQEntSize
C Eval Idx = Idx + 1
C Eval QualMsgQ = MsgQEntStr(Idx)
* only msgq show onec
* regardless of number times used.
C If AryIdx = 0 or
C %lookup(MsgQ :MsgQUsrAry:1:AryIdx) = 0
C Eval AryIdx = AryIdx + 1
C Eval MsgQUsrAry(AryIdx) = MsgQ
C EndIf
C EndDo
*----------------------------------------------------------------
* Create user space
C callp QUSCRTUS(
C uSpaceName:
C 'TEST':
C 1500000:
C x'00':
C '*ALL':
C 'User Space CHKJOBLOG' :
C '*YES':
C vApiErrDs)
* set UserSpace to autoextended
C CallP QUSCUSAT( QUSLib :
C uSpaceName :
C QUSAttr :
C vApiErrDs )
* Get pointer to user space
C callp QUSPTRUS(
C uSpaceName:
C uHeadPtr:
C vApiErrDs)
* call api to load job log into user space.
C callp QMHLJOBL(
C uSpaceName:
C 'LJOB0100':
C MsgSelectDS:
C %len(MsgSelectDS):
C 'JSLT0100':
C vApiErrDs)
* Process elements
*
C eval uListPtr = uHeadPtr + uOffSetToList
1B C do uNumOfEntrys
* Message Type Example
* 15 Escape, exception already handled when API is called MCH1211
* 17 Escape, exception not handled when API is called CPF9999
* 06 Sender's copy RNQ0102
*
* Example Error: divide by zero
* Job log sequence : MCH1211 Attempt made to divide by zero
* for fixed point operation.
* CPF9999 Function check. MCH1211
* unmonitored by TESTERR at statement 0000000007, instruction X'0000'
* reply message=> RNQ0102 Attempt to divide by zero (C G D F).
C If uMsgType = '06' or
C uMsgType = '15' or
C uMsgType = '17'
C eval uListPtr2 = uHeadPtr + uOffsetToFlds
C If uMsgType = '15'
C eval msgtxt15 =
C %subst(u2Data:1:U2LengthOfData)
C EndIf
C If uMsgType = '17'
C eval msgtxt17 =
C %subst(u2Data:1:U2LengthOfData)
C EndIf
C If uMsgType = '06'
C eval msgtxt06 =
C %subst(u2Data:1:U2LengthOfData)
C EndIf
C EndIf
C eval uListPtr = uHeadPtr + uOffsetToNext
1E C enddo
C eval msgtxt = '*** Job MSGW Error Message' +
C ' *** ' +
C 'Job ' +
C %trim(jobnumber) + '/' +
C %trim(jobuser) + '/' +
C %trim(jobname) + ' ' +
C 'error text:' + ' ' +
C %trim(msgtxt15) + ' ' +
C %trim(msgtxt17) + ' ' +
C %trim(msgtxt06)
C eval msgtxt494 = msgtxt
C if %len(%trim(msgtxt15) +
C %trim(msgtxt17) +
C %trim(msgtxt06)) > 0
C exsr SndEzMsg
C EndIf
C return
**********************************************************************
C SndEzMsg BegSr
C callp QEZSNDMG( msgTypeA
C : '*BREAK'
C : msgtxt494
C : %len(msgtxt494)
C : MsgQUsrAry
C : AryIdx
C : sentcode
C : funccode
C : ErrorCode
C : 'N'
C : *blanks
C : '*USR'
C : 0 )
C EndSr
File : QCMDSRC
Member : RTVMSGWJL
Type : CMD
Usage : CRTCMD CMD(your-lib/RTVMSGWJL) PGM(your-lib/RTVMSGWJLR)
/* =============================================================== */
/* = Command....... RtvMsgwJL = */
/* = Source type... CMD = */
/* = Description... Retrieve MSGW Job ErrMsg from Job Log = */
/* = = */
/* = CPP........... RtvMsgwJLR = */
/* = = */
/* =============================================================== */
/* = Date : 2008/03/21 = */
/* = Author: Vengoal Chang = */
/* =============================================================== */
/* = Create strp: = */
/* = CRTBNDRPG PGM(RtvMsgwJLR) SRCFILE(LIB/QRPGLESRC) = */
/* = CRTCMD CMD(RtvMsgwJL) PGM(RtvMsgwJLR) + = */
/* = SRCFILE(LIB/QCMDSRC) = */
/* =============================================================== */
/*------------------------------------------------*/
/* Command Definition */
/*------------------------------------------------*/
CMD PROMPT('RTV MSGW Job Log and Send')
PARM KWD(JOB) TYPE(*SNAME) LEN(10) MIN(1) +
PROMPT('Job name')
PARM KWD(USER) TYPE(*SNAME) LEN(10) MIN(1) +
PROMPT('User name')
PARM KWD(JOBNBR) TYPE(*CHAR) LEN(6) RANGE(000000 +
999999) MIN(1) PROMPT('Job number')
PARM KWD(MSGTYPE) TYPE(*CHAR) LEN(5) RSTD(*YES) +
DFT(*INFO) VALUES(*INFO *INQ) +
PROMPT('Message type')
PARM KWD(TOMSGQ) TYPE(MSGQ) MAX(20) PROMPT('Send +
log to message queue')
MSGQ: QUAL TYPE(*NAME) LEN(10) SPCVAL((QSYSOPR)) +
EXPR(*YES)
QUAL TYPE(*NAME) LEN(10) DFT(*LIBL) +
SPCVAL((*LIBL) (*CURLIB)) EXPR(*YES) +
PROMPT(Library)
File : QRPGLESRC
Member : TESTERR
Type : RPGLE
Usage : 測試程式
此測試程式用於產生除以 0 的錯誤
CRTBNDRPG TESTERR
D num1 S 10I 0
D num2 S 10I 0
D result S 10I 0
C eval *InLr = *On
C eval result = num1/ num2
C
TESTERR 編譯後,執行下列指令:
sbmjob cmd(call testerr) job(testerr)
WRKACTJOB 檢視 JOB TESTERR 執行狀態是 MSGW,記下該 JOB 的 JOB name, Job user, Job number
執行 RTVMSGWJL JOB(jobname) USER(jobuser) JOBNBR(jobnbr) TOMSGQ(anyoneuser)
例如執行 RTVMSGWJL JOB(TESTERR) USER(VENGOAL) JOBNBR(509363) TOMSGQ(VENGOAL)
會收到如下訊息:
>From . . . : VENGOAL 05/16/08 11:19:15
*** Job MSGW Error Message *** Job 509363/VENGOAL/TESTERR error text
Attempt made to divide by zero for fixed point operation. Function
check. MCH1211 unmonitored by TESTERR at statement 0000000007,
instruction X'0000'. Attempt to divide by zero (C G D F).
回本期目錄
星期二, 11月 07, 2023
2006-12-20 如何擷取某工作 Joblog 中某一 MsgID 的訊息內容是否包含指定字串?(Command SCNJOBLOG)
如何擷取某工作 Joblog 中某一 MsgID 的訊息內容是否包含指定字串?(Command SCNJOBLOG)
File : QRPGLESRC
Member: SCNJOBMSGR
Type : RPGLE
Usage : CRTBNDRPG SCNJOBMSGR
H DFTACTGRP(*NO) ACTGRP(*CALLER) BNDDIR('QC2LE') EXPROPTS(*RESDECPOS)
H DATFMT(*ISO) TIMFMT(*ISO) OPTION(*NODEBUGIO) DEBUG
*----------------------------------------------------------------
* SCNJOBLOG Scan specified job's job log by MSGID to
* search some string in job log
* Copyright (C) 12/12/2006 Vengoal Chang
* This program is free software, you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation.
*
*----------------------------------------------------------------
* This program retrieve specified job job's log and return found
* search string or not.
*
* CRTBNDRPG with target release V5R1 and later
*
*----------------------------------------------------------------
* api (application program interfaces) used:
* quscrtus create user space
* qusptrus retrieve pointer to user space
* qmhljobl list job log messages
* qmhsndm send non-program messages
*----------------------------------------------------------------
D uSpaceName s 20 inz('RTVJOBLOG QTEMP ')
D msgtxt s 256
D QUSLIB s 10
* -------------------------------------------------------------------
* - User space attributes data structure -
* -------------------------------------------------------------------
D QUSAttr DS
D QUSNumRec 10I 0 Inz( 1 )
D QUSKey 10I 0 Inz( 3 )
D QUSRecLen 10I 0 Inz( 1 )
D QUSRecData 1A Inz( '1' )
*----------------------------------------------------------------
D struct DS
D msgdln 10I 0
D msgq# 10I 0
D msgkey 4
D msgq 20 INZ('QSYSOPR *LIBL ')
*
*----------------------------------------------------------------
* Get user space list info from header section.
*----------------------------------------------------------------
D ds based(uHeadPtr)
D uOffSetToList 125 128i 0
D uNumOfEntrys 133 136i 0
D uSizeOfEntry 137 140i 0
*
D uListEntry1 ds Based(uListPtr )
D uOffsetToNext 10i 0 overlay(uListEntry1:1)
D uOffsetToFlds 10i 0 overlay(uListEntry1:5)
D uNumFldsRetrnd 10i 0 overlay(uListEntry1:9)
D uMsgSeverity 10i 0 overlay(uListEntry1:12)
D uMsgId 7a overlay(uListEntry1:17)
D uMsgType 2a overlay(uListEntry1:24)
D uMsgKey 4a overlay(uListEntry1:26)
D uMsgFile 20a overlay(uListEntry1:30)
D uMsgFileName 10a overlay(uListEntry1:30)
D uMsgFileLib 10a overlay(uListEntry1:40)
* these fields repeat for each key selected.
D uListEntry2 ds Based(uListPtr2)
D u2OffsetToNext 10i 0
D u2LengthOfFlds 10i 0
D u2IdentifierF 10i 0
D u2TypeOfData 1a
D u2StatOfData 1a
D u2Reserved 14a
D u2LengthOfData 10i 0
D u2Data 500
*----------------------------------------------------------------
* Error return code parm for APIs.
*----------------------------------------------------------------
D vApiErrDs ds
D vbytpv 10i 0 inz(%size(vApiErrDs))
D vbytav 10i 0 inz(0)
D vmsgid 7a
D vresvd 1a
D vrpldta 50a
*
*----------------------------------------------------------------
* Message selection data structure.
*
* Retrieve JOB Log direction
*-----------------------------|-------------|--------------------
* Parameter | From Top | From Bottom
*-----------------------------|-------------|--------------------
* msListDirection | *NEXT | *PRV
* msStartingMessageKey | X'00000000' | X'FFFFFFFF'
*----------------------------------------------------------------
D MsgSelectDS ds
D msMaxMsgRequested...
D 10i 0 inz(-1) overlay(msgSelectDS:1) num of msg requested
D msListDirection...
D 10a inz('*NEXT') overlay(msgSelectDS:5) List direction
D msQualifiedJobName...
D 10a inz('*') overlay(msgSelectDS:15) * = current job
D msQualifiedUserName...
D 10a inz(' ') overlay(msgSelectDS:25) = current job
D msQualifiedJobNumber...
D 6a inz(' ') overlay(msgSelectDS:35) = current job
D msInternalJobIdentifier...
D 16a inz(' ') overlay(msgSelectDS:41) = current job
D msStartingMessageKey...
D 4a inz(x'00000000') start newest message
D overlay(msgselectDS:57)
D msMaxMsgLength...
D 10i 0 inz(500) overlay(msgSelectDS:61) id 301,302 lengths
D msMaxMsgHelpLength...
D 10i 0 inz(100) overlay(msgSelectDS:65) id 401,402,403,404
D msOffsetToIdentifiersOfFieldstoReturn...
D 10i 0 inz(84) overlay(msgSelectDS:69) to start of array
D msNumberOfFieldsToReturn...
D 10i 0 inz(1) overlay(msgSelectDS:73)
D msOffsetToCallMsgQname...
D 10i 0 inz(88) overlay(msgSelectDS:77)
D msLengthOfCallMsgQname...
D 10i 0 inz(1) overlay(msgSelectDS:81)
D msIndentifiersOfFieldsToReturn...
D 10i 0 inz(0302) overlay(msgSelectDS:85)
D msCallMessageQueueName...
D 1a inz('*') overlay(msgSelectDS:89)
*----------------------------------------------------------------
* Create Prototypes for calls
* --------------------------------------------------------------------
* - QusCrtUs - Create User Space API -
* - -
* - Usage Length Type Parameter Description -
* - -
* - Input 20 Character Qualified user space name -
* - Input 10 Character Extended attribute -
* - Input 4 0 Binary Initial size -
* - Input 1 Character Initial value -
* - Input 10 Character Public authority -
* - Input 50 Character Text description -
* --------------------------------------------------------------------
D quscrtus PR ExtPgm('QUSCRTUS')
D 20
D 10 const
D 10i 0 const
D 1 const
D 10 const
D 50 const
D 10 const
Db like(vApiErrDS)
* -------------------------------------------------------------------
* - Qusptrus - Get user space pointer API -
* - -
* - Usage Length Type Parameter Description -
* - -
* - Input 20 Character Qualified user space name -
* - Output * Pointer UserSpace Pointer -
* - Output Error Code -
* - -----------------------------------------------------------------
D qusptrus PR ExtPgm('QUSPTRUS') retrieve pointer
D 20 Space Name
D * pointer
Db like(vApiErrDS) error parm
* -------------------------------------------------------------------
* - Quscusat - Change User Space Attributes API -
* - -
* - Usage Length Type Parameter Description -
* - -
* - Output 10 Character Returned library -
* - Input 20 Character Qualified user space name -
* - Input 13 Character Attribute structure -
* - Output Error code -
* -------------------------------------------------------------------
D quscusat PR ExtPgm( 'QUSCUSAT' )
D 10A Const
D 20A Const
D 13A Const
Db like(vApiErrDS)
* ---------------------------------------------------------------
D system PR 10I 0 extproc('system')
D i_cmd * value options(*string)
*
D EXCP_MSGID S 7A import('_EXCP_MSGID')
* --------------------------------------------------------------
D qmhljobl PR ExtPgm('QMHLJOBL ')
D 20
D 8 const
Db like(MsgSelectDS)
D 10i 0 const
D 8 const
Db like(vApiErrDS)
* --------------------------------------------------------------
D SNDPGMMSG PR EXTPGM('QMHSNDPM')
D MESSAGEID 7A CONST
D QUALMSGF 20A CONST
D MSGDATA 256A CONST
D MSGDTALEN 10I 0 CONST
D MSGTYPE 10A CONST
D CALLSTKENT 10A CONST
D CALLSTKCNT 10I 0 CONST
D MESSAGEKEY 4A
D ERRORCODE 32766A OPTIONS(*VARSIZE)
* --------------------------------------------------------------
D main PR extpgm('SCNJOBLOGR')
D jobname 10
D jobuser 10
D jobnumber 6
D msgId 7
D searchStr 48
D includeQuote 4
D StrFound 1
D main PI
D jobname 10
D jobuser 10
D jobnumber 6
D msgId 7
D searchStr 48
D includeQuote 4
D StrFound 1
D searchString S 50
D strpos S 5I 0
D quote S 1 Inz('''')
D WWMSGLEN S 10I 0
D WWTHEKEY S 4A
*----------------------------------------------------------------
C eval msQualifiedJobName = jobname
C eval msQualifiedUserName = jobuser
C eval msQualifiedJobNumber = jobnumber
C If includeQuote = '*YES'
C eval searchString = quote + %trim(searchStr) +
C quote
C Else
C eval searchString = %trim(searchStr)
C EndIf
C eval StrFound = '0'
*----------------------------------------------------------------
* Create user space
C callp QUSCRTUS(
C uSpaceName:
C 'TEST':
C 1500000:
C x'00':
C '*ALL':
C 'User Space RTVJOBLOG' :
C '*NO':
C vApiErrDs)
* set UserSpace to autoextended
C CallP QUSCUSAT( QUSLib :
C uSpaceName :
C QUSAttr :
C vApiErrDs )
* Get pointer to user space
C callp QUSPTRUS(
C uSpaceName:
C uHeadPtr:
C vApiErrDs)
* call api to load job log into user space.
C callp QMHLJOBL(
C uSpaceName:
C 'LJOB0100':
C MsgSelectDS:
C %len(MsgSelectDS):
C 'JSLT0100':
C vApiErrDs)
* Process elements
*
C If vbytav = 0
C eval uListPtr = uHeadPtr + uOffSetToList
1B C do uNumOfEntrys
C If uMsgId = msgId
C eval uListPtr2 = uHeadPtr + uOffsetToFlds
C eval msgtxt = %subst(u2Data:1:U2LengthOfData)
C eval strPos = %scan(%trim(searchString) : msgtxt)
C If strPos > 0
C eval StrFound = '1'
C leave
C EndIf
C EndIf
C eval uListPtr = uHeadPtr + uOffsetToNext
1E C enddo
C Else
C eval msgtxt = 'API Error: ' + vmsgid +
C '. Please see job log for detail'
C eval WWMSGLEN = %len(%trimr(msgtxt))
C CALLP SNDPGMMSG('CPF9897': 'QCPFMSG *LIBL':
C msgtxt:WWMSGLEN: '*ESCAPE':
C '*PGMBDY': 1: WWTHEKEY: vApiErrDs)
C EndIf
C eval *inlr = *on
C return
File : QCMDSRC
Member: SCNJOBMSG
Type : CMD
Usage : CRTCMD CMD(lib/SCNJOBLOG) PGM(lib/SCNJOBLOGR) ALLOW(*IPGM *BPGM)
/********************************************************************/
/* Title: SCNJOBLOG: Scan jobs log */
/* */
/* Description - This command performs job log scaned by MSGID */
/* */
/* The Create Command command should include the following: */
/* */
/* CRTCMD CMD(SCNJOBLOG) PGM(SCNJOBLOGR) */
/* ALLOW(*IPGM *BPGM) */
/********************************************************************/
/* =============================================================== */
/* = Date : 2006/12/20 = */
/* = Author: Vengoal Chang = */
/* =============================================================== */
/*------------------------------------------------*/
/* Command Definition */
/*------------------------------------------------*/
CMD PROMPT('Scan Job Log by MSGID')
PARM KWD(JOB) TYPE(*SNAME) LEN(10) MIN(1) +
PROMPT('Job name')
PARM KWD(USER) TYPE(*SNAME) LEN(10) MIN(1) +
PROMPT('User name')
PARM KWD(JOBNBR) TYPE(*CHAR) LEN(6) RANGE(000000 +
999999) MIN(1) PROMPT('Job number')
PARM KWD(MSGID) TYPE(*CHAR) LEN(7) SPCVAL((*ALL)) +
MIN(1) PROMPT('Message ID to be searched')
PARM KWD(SCHSTR) TYPE(*CHAR) LEN(50) +
PROMPT('String searched in MSGID Text')
PARM KWD(QUOTE) TYPE(*CHAR) LEN(4) RSTD(*YES) +
DFT(*NO) VALUES(*YES *NO) PROMPT('Include +
quote between SCHSTR')
PARM KWD(FOUND) TYPE(*CHAR) LEN(1) RTNVAL(*YES) +
PROMPT('CL var for String found (1)')
File : QCLSRC
Member: SCNJOBLOGT
Type : CLP
Usage : 指定 job, usr, jobnbr, search-msgid, search-string 取代小寫部分
CRTCLPGM SCNJOBLOGT
CALL SCNJOBLOGT
PGM
DCL &RC *CHAR 1 /* RC=1 found, RC <> 1 not found */
SCNJOBLOG JOB(job) USER(usr) JOBNBR(jobnbr) +
MSGID(search-msgid) SCHSTR(search-string) FOUND(&RC)
MONMSG CPF9897
ENDPGM
星期一, 11月 06, 2023
2004-11-20 如何將訊息紀錄於 JobLog ? (API Qp0zLprintf(Print Formatted Job Log Data))
如何將訊息紀錄於 JobLog ? (API Qp0zLprintf(Print Formatted Job Log Data))
將訊息紀錄於 JobLog 有幾種方式, 可以呼叫 CL 指令 SNDPGMMSG 或 API QMHSNDPM ,
但是有一 API Qp0zLprintf (Print Formatted Job Log Data) 更容易使用, 其參數
使用方式如同 C 函式 printf, 但必須於字串尾端加上 X'25' 表示訊息結尾.
File : QRPGLESRC
Member: WRTJOBLOGR
Type : RPGLE
Usage : CRTBNDRPG WRTJOBLOGR
: CALL WRTJOBLOGR
H DEBUG OPTION(*SRCSTMT:*NODEBUGIO) DFTACTGRP(*NO) ACTGRP(*CALLER)
D Qp0zLprintf PR 10I 0 ExtProc('Qp0zLprintf')
D szOutputStg * Value OPTIONS(*STRING)
D * Value OPTIONS(*STRING:*NOPASS)
D * Value OPTIONS(*STRING:*NOPASS)
D * Value OPTIONS(*STRING:*NOPASS)
D * Value OPTIONS(*STRING:*NOPASS)
D * Value OPTIONS(*STRING:*NOPASS)
D * Value OPTIONS(*STRING:*NOPASS)
D * Value OPTIONS(*STRING:*NOPASS)
D * Value OPTIONS(*STRING:*NOPASS)
D * Value OPTIONS(*STRING:*NOPASS)
D * Value OPTIONS(*STRING:*NOPASS)
D ProdNo S 5 0 Inz(1234)
D ProdName S 30 Inz('Testing')
C Callp Qp0zLprintf('Hello OS/400'+X'25')
C callp Qp0zLprintf('ProdNo: %s %s' + X'25' :
C %char(ProdNo):%Trimr(ProdName))
C Eval *InLr = *On
執行 CALL WRTJOBLOGR 後, DSPJOBLOG 會有如下訊息:
Hello OS/400
ProdNo: 1234 Testing
此 API 非常方便於除錯或紀錄程式執行狀態.
2004-10-18 如何於 RPG 中將程式執行中的訊息寫入 JobLog 中 ?(API QMHSNDPM)
如何於 RPG 中將程式執行中的訊息寫入 JobLog 中 ?(API QMHSNDPM)
File : QRPGLESRC
Member: SNDPGMMSGR
Type : RPGLE
Usage : CRTBNDRPG SNDPGMMSGR
CALL SNDPGMMSGR
畫面 24 行會顯示此程式所傳送之訊息,同時此訊息亦會寫入JOBLOG,可以執行
DSPJOBLOG 顯示 Job Log(工作日誌)。
此範例中有四種訊息傳送方式,最常使用是 *INFO(一般資訊), *COMP(程式執行完成時的訊息),
*DIAG(程式錯誤偵測訊息), *ESCAPE(程式執行錯誤訊息),一般當系統偵測到程式執行錯誤時,
會先發送 *DIAG 訊息,再發送 *ESCAPE 訊息,但是如果是自己所寫的程式可以直接發送
*ESCAPE 訊息,通知系統程式不正常結束。
H dftactgrp(*NO)
D sndpgmmsg PR
D peMsg 256A const
D outMsgType 10A const
C callp sndpgmmsg('test *INFO' : '*INFO')
C callp sndpgmmsg('test *COMP' : '*COMP')
C callp sndpgmmsg('test *DIAG' : '*DIAG')
C callp sndpgmmsg('test *ESCAPE msg' : '*ESCAPE')
C eval *InLr = *On
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* This ends this program abnormally, and sends back an escape.
* message explaining the failure.
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P sndpgmmsg B
D sndpgmmsg PI
D peMsg 256A const
D outMsgType 10A const
D QMHSNDPM PR ExtPgm('QMHSNDPM')
D MessageID 7A Const
D QualMsgF 20A Const
D MsgData 256A Const
D MsgDtaLen 10I 0 Const
D MsgType 10A Const
D CallStkEnt 10A Const
D CallStkCnt 10I 0 Const
D MessageKey 4A
D ErrorCode 32766A options(*varsize)
D dsEC DS
D dsECBytesP 1 4I 0 INZ(256)
D dsECBytesA 5 8I 0 INZ(0)
D dsECMsgID 9 15
D dsECReserv 16 16
D dsECMsgDta 17 256
D wwMsgLen S 10I 0
D wwTheKey S 4A
c eval wwMsgLen = %len(%trimr(peMsg))
c if wwMsgLen<1
c return
c endif
c callp QMHSNDPM('CPF9897': 'QCPFMSG *LIBL':
c peMsg: wwMsgLen: %trim(outMsgType):
c '*PGMBDY': 1: wwTheKey: dsEC)
c* callp QMHSNDPM('CPF9897': 'QCPFMSG *LIBL':
c* peMsg: wwMsgLen: %trim(outMsgType):
c* '*': 3: wwTheKey: dsEC)
c return
P E
星期四, 11月 02, 2023
Best Practices for Managing Job Logs on IBM i
https://www.redbooks.ibm.com/abstracts/tips0679.html?Open
For our discussion, we focus on why are job logs kept and whether you can use a more granular control.
First, you can set up a job’s logging level to get all messages logged to the job log, but the job log is produced only if the job ends abnormally. If the job ends normally, no job log is generated, using the LOG(4 0 *NOLIST) setting.
When ending jobs, you can indicate that you do not want a job log, as shown in the following table.
| Command | Parameter for no job log |
| End Job (ENDJOB) | LOGLMT(0) |
| End Prestart Jobs (ENDPJ) | LOGLMT(0) |
| End Group Job (ENDGRPJOB) | LOG(*NOLIST) |
| End Subsystem (ENDSBS) | ENDSBSOPT(*NOJOBLOG) |
| End System (ENDSYS) | ENDSBSOPT(*NOJOBLOG) |
| Power Down System (PWRDWNSYS) | ENDSBSOPT(*NOJOBLOG) |
| Clear Job Queue (CLRJOBQ) | LOG(*NONE) |
| Sign Off (SIGNOFF) | LOG(*NOLIST) |
Consider the following system values with associated job attributes for job log characteristics:
- QJOBMSGQFL: Job message queue full action
This system value determines the behavior when the job message queue is full.
*NOWRAP ends the job when the job message queue is full. Use this value to prevent short running jobs from looping endlessly in error situations.
*WRAP allows new messages to overlay old messages when the job message queue is full. Use this value for long running jobs.
*PRTWRAP creates a spooled file for the job log prior to wrapping to allow new messages to overlay old messages.
- QJOBMSGQMX: Maximum size of job message queue
This system value sets the size of a job’s message queue. The shipped value is 16 MB, which for many jobs might be too high. Setting this system value to a high number can over commit a system’s storage. For example, if you have 20 000 active jobs and set QJOBMSGQMX to 64, the system can (in the worst case) use 1 280 000 megabytes for job message queues. Even systems that are large enough to run a lot of active jobs probably do not have that much unused DASD. When jobs hit a common error loop, even if it is only 5% of the active jobs, you can start losing storage quickly. Two points:
You need to set limits using the system value and the job description values.
The system uses storage to run. It uses a lot more storage to handle errors, and you need a fairly wide margin to avoid running out of storage.
Setting QJOBMSGQMX to 8 and QJOBMSGQFL set to *WRAP is a good, general configuration. If you have a specific need for a larger job log, set these values with care and with knowledge about the jobs that specifically need that high of a job log for special problem cases. Setting the QJOBMSGQMX system value to 8 limits the number of job log messages for a job. It can also reduce the recovery time for IPL after some system failures.
- QLOGOUTPUT: Job log output
This system value allows you to control if, and when, spooled job logs are created.
*JOBEND specifies that job logs are spooled when the job ends. Only use *JOBEND if you have a dependency on the job log being available immediately after the job ends. When many jobs end at the same time, using *JOBEND can result in a CPU spike as well as potential contention on the output queue.
*JOBLOGSVR specifies that job logs are spooled by the Job Log Servers some time after the job ends. Using *JOBLOGSVR is fairly close to using *JOBEND and tends to operate more smoothly (with less contention and less CPU spike).
You might want to shut down the job log servers to a restricted state before ending the jobs, depending on how much sequencing you do when ending work. Ending the job log servers prior to going into restricted state prevents the writing of job logs for jobs that are being ended (assuming those jobs use *JOBLOGSVR). IBM generally recommends using *JOBLOGSVR.
*PND keeps the job logs in a pending state until they are spooled or deleted from the system. Pending job logs reduce CPU and contention. Pending job logs, however, consume a job structure, even if you are detaching spooled files. The job descriptions for several server jobs are configured to use LOGOUTPUT(*PND), helping to avoid CPU spikes and contention when large number of server jobs end at the same time. The automatic cleanup function (GO CLEANUP) deletes pending job logs in the same manner as spooled job logs; however, if you are not using the system’s cleanup feature, then you must do your own cleanup. Cleanup is not optional, because if cleanup is not done, the system can run out of job structures or can fill with spooled files. To clean up pending job logs, use the QWTRMVJL API:
Specify a zero value for the “days since job completion” parameter to clean up the job logs immediately. Finally, if you are using the QMHCTLJL API, do not use pending job logs. Using the control job log output API makes sense only if you are creating the job log when the job ends.V5R4 introduced the WRKJOBLOG command. You can delete job logs from this interface. In V6R1, you have the option to delete all job logs.
- QJOBMSGQSZ: Job message queue initial size
This system value is obsolete and no longer used.
- QJOBMSGQTL: Job message queue maximum initial size.
This system value is obsolete and no longer used.
For a more detailed discussion about this topic, refer to Best Practices for Managing IBM i Jobs and Output (and a few other special tips), REDP-4454.