Log message to IFS file with command LOGTOIFS
File : QRPGLESRC
Member: LOGTOIFS
Type : RPGLE
Usage : CRTBNDRPG PGM(LOGTOIFS) SRCFILE(LIBxx/QRPGLESRC) SRCMBR(LOGTOIFS)
**===============================================================
** Command....... LogToIfs =
** CPP........... LogToIfs RPGLE =
** Description... Log Message to IFS File =
**===============================================================
** Date : 2016/12/26 =
** Author: Vengoal Chang =
**===============================================================
** =
** To compile: =
** CRTBNDRPG LOGTOIFS SRCFILE(lib/QRPGLESRC) DBGVIEW(*LIST) =
** =
**===============================================================
H DftActGrp(*NO)
H Debug Option(*SrcStmt:*NoDebugIo)
* PGM SDS
D SDS
D psdsPgmName *Proc
D psdsPgmLib 81 90 * Program library
D JobNam 244 253
D JobUsr 254 263
D JobNbr 264 269
D CurUsr 358 367
** API call to open a stream file
**
D open PR 10I 0 ExtProc('open')
D path * value options(*string)
D openflags 10I 0 value
D mode 10U 0 value options(*nopass)
D ccsid 10U 0 value options(*nopass)
D txtcreatid 10U 0 value options(*nopass)
D**********************************************************************
D* Flags for use in open()
D*
D* More than one can be used -- add them together.
D**********************************************************************
D* Writing Only
D O_WRONLY C 2
D* Create File if not exist
D O_CREAT C 8
D* Truncate File to 0 bytes
D O_TRUNC C 64
* Append to file
D O_APPEND C 256
D* Convert text by code-page
D O_CODEPAGE C 8388608
D* Convert text by ccsid
D O_CCSID C 32
D* Open in text-mode
D O_TEXTDATA C 16777216
* Note: O_TEXT_CREAT requires all of the following flags to work:
* O_CREAT+O_TEXTDATA+(O_CODEPAGE or O_CCSID)
D O_TEXT_CREAT C 33554432
D* owner authority
D**********************************************************************
D* Mode Flags.
D* basically, the mode parm of open(), creat(), chmod(),etc
D* uses 9 least significant bits to determine the
D* file's mode. (peoples access rights to the file)
D*
D* user: owner group other
D* access: R W X R W X R W X
D* bit: 8 7 6 5 4 3 2 1 0
D*
D* (This is accomplished by adding the flags below to get the mode)
D**********************************************************************
D S_IRUSR C 256
D S_IWUSR C 128
D S_IXUSR C 64
D S_IRWXU C 448
D* group authority
D S_IRGRP C 32
D S_IWGRP C 16
D S_IXGRP C 8
D S_IRWXG C 56
D* other people
D S_IROTH C 4
D S_IWOTH C 2
D S_IXOTH C 1
D S_IRWXO C 7
** API call to write data to a stream file
**
D write PR 10I 0 extproc('write')
D fildes 10I 0 value
D buf * value
D nbyte 10U 0 value
** API call to close a stream file
**
D close PR 10I 0 extproc('close')
D fildes 10I 0 value
D @__ERRNO PR * EXTPROC('__errno')
D STRERROR PR * EXTPROC('strerror')
D ERRNUM 10I 0 VALUE
D ERRNO PR 10I 0
D DIE PR
D PEMSG 256A CONST
D GetCaller PR
D CallingPgmNam 10
D CallingPgmLib 10
D fd S 10I 0
D data S 4096A
D IfsPath S 256A
D Curtime S Z
D PgmNam S 10
D PgmLib S 10
D Proc S 32
* Program parameters - title and page length in lines
D paIfsFile S 64
D paPath S 256
D paMessage S 2048
D paIncludeJob S 4
* Program parameters
C *Entry Plist
C Parm paIfsFile
C Parm paPath
C Parm paMessage
C Parm paIncludeJob
c eval *inlr = *on
C eval IfsPath = %trim(paPath) + '/' +
C %trim(paIfsFile)
C* Create an empty file
c eval fd = open(%trim(IfsPath)
c : O_CREAT + O_APPEND + O_WRONLY
c + O_CCSID + O_TEXT_CREAT
c + O_TEXTDATA
c : S_IWUSR+S_IRUSR+S_IRGRP+S_IROTH
c : 0
c : 0 )
c if fd < 0
c callp die('open(): ' + %Char(ERRNO) + ' ' +
c %trim(IfsPath) + ' ' +
c %STR(STRERROR(ERRNO)))
c return
c endif
C Time Curtime
C If paIncludeJob = '*YES'
C callp GetCaller ( PgmNam
C : PgmLib
C )
C eval data = %SubSt(%Char(Curtime):1:23)+ ' ' +
C JobNam + ' ' +
C JobUsr + ' ' +
C JobNbr + ' ' +
C PgmLib + ' ' +
C PgmNam + ' ' +
C %trimR(paMessage) + x'0D25'
C Else
C eval data = %SubSt(%Char(Curtime):1:23)+ ' ' +
C %trimR(paMessage) + x'0D25'
C EndIf
C
c callp write(fd: %addr(data): %len(%trim(data)))
C* Close the file:
c callp close(fd)
**********************************************************************
* Get Caller with Retrieve Call Stack API
**********************************************************************
P GetCaller B
D GetCaller PI
D CallingPgmNam 10
D CallingPgmLib 10
D RtvCallStack PR Extpgm('QWVRCSTK')
D 2000
D 10I 0
D 8 CONST
D 56
D 8 CONST
D 15
D Var DS 2000
D BytAvl 10I 0
D BytRtn 10I 0
D Entries 10I 0
D Offset 10I 0
D EntryCount 10I 0
D VarLen S 10I 0 Inz(%size(Var))
D ApiErr S 15
D JobIdInf DS
D JIDQName 26 Inz('*')
D JIDIntID 16
D JIDRes3 2 Inz(*loval)
D JIDThreadInd 10I 0 Inz(1)
D JIDThread 8 Inz(*loval)
D Entry DS 256
D EntryLen 10I 0
D PgmNam 10 Overlay(Entry:25)
D PgmLib 10 Overlay(Entry:35)
c eval CallingPgmNam = *blanks
c eval CallingPgmLib = *blanks
c callp RtvCallStack ( Var
c : VarLen
c : 'CSTK0100'
c : JobIdInf
c : 'JIDF0100'
c : ApiErr
c )
C Do EntryCount
C Eval Entry = %subst(Var:Offset + 1)
c if CallingPgmNam = *blanks and
c CallingPgmLib = *blanks
c if PgmNam = psdsPgmName and
c PgmLib = psdsPgmLib
C Else
c eval CallingPgmNam = Pgmnam
c eval CallingPgmLib = Pgmlib
C Endif
C Endif
C Eval Offset = Offset + EntryLen
C Enddo
C
C Return
P GetCaller E
**********************************************************************
* This ends this program abnormally, and sends back an escape.
* message explaining the failure.
**********************************************************************
P DIE B
D DIE PI
D PeMsg 256A CONST
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 CallStkCct 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 SndPgmMsg('CPF9897': 'QCPFMSG *LIBL':
C PeMsg: WWMsgLen: '*ESCAPE':
C '*PGMBDY': 1: WWTheKey: Dsec)
C RETURN
P DIE E
**********************************************************************
* This procedure return call socket C API errno
**********************************************************************
P ErrNo B
D ErrNo PI 10I 0
D P_EeeNo S *
D WWReturn S 10I 0 Based(P_Errno)
C EVAL P_Errno = @__Errno
C RETURN WWReturn
P Errno E
File : QCMDSRC
Member: LOGTOIFS
Type : CMD
Usage : CrtCmd Cmd( LogToIfs )
Pgm( LogToIfs )
SrcFile( QCMDSRC )
/* =============================================================== */
/* = Command....... LogToIfs = */
/* = CPP........... LogToIfs RPGLE = */
/* = Description... Log Message to IFS File = */
/* = = */
/* = CrtCmd Cmd( LogToIfs ) = */
/* = Pgm( LogToIfs ) = */
/* = SrcFile( QCMDSRC ) = */
/* =============================================================== */
/* = Date : 2016/12/26 = */
/* = Author: Vengoal Chang = */
/* =============================================================== */
Cmd Prompt('Log Message To IFS File')
Parm Kwd(ToStmf) +
Type(*Name) Len(64) Min(1) +
Prompt('To stream file name')
Parm Kwd(ToDir) +
Type(*Pname) LEN(256) MIN(1) +
Prompt('To directory')
Parm Kwd(LogMsg) +
Type(*Char) Len(2048) Min(1) +
Prompt('Log message')
Parm Kwd(InCldJob) +
Type(*Char) Len(4) +
Rstd(*Yes) +
Dft(*No ) +
Values(*YES *NO) +
Prompt('Log include job info')
Usage example:
Log Message To IFS File (LOGTOIFS)
Type choices, press Enter.
To stream file name . . . . . .
To directory . . . . . . . . . .
Log message . . . . . . . . . .
...
Log include job info . . . . . . *NO *YES, *NO
LOGTOIFS TOSTMF(AP1LOG.TXT) TODIR('/tmp') LOGMSG('test 2') INCLDJOB(*YES)
LOGTOIFS TOSTMF(AP1LOG.TXT) TODIR('/tmp') LOGMSG('test 3') INCLDJOB(*YES)
LOGTOIFS TOSTMF(AP1LOG.TXT) TODIR('/tmp') LOGMSG('test 3')
LOGTOIFS TOSTMF(AP1LOG.TXT) TODIR('/tmp') LOGMSG('test 4')
DSPF STMF('/tmp/AP1LOG.TXT')
Browse : /tmp/AP1LOG.TXT
Record : 1 of 4 by 14 Column : 1 59 by 79
Control :
....+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....
************Beginning of data**************
2016-12-26-15.25.45.104 QPADEV0047 USRTEST 317148 QSYS QUOCMD test 2
2016-12-26-15.25.50.561 QPADEV0047 USRTEST 317148 QSYS QUOCMD test 3
2016-12-26-15.25.57.791 test 3
2016-12-26-15.26.02.863 test 4
************End of Data********************
A blog about IBM i (AS/400), MQ and other things developers or Admins need to know.
星期四, 11月 09, 2023
2016-12-26 Log message to IFS file with command LOGTOIFS
星期四, 11月 02, 2023
2002-10-16 如何檢查 Job Log ? (Command CHKJOBLOG 利用 QMHLJOBL List Job Log API)
如何檢查 Job Log ? (Command CHKJOBLOG 利用 QMHLJOBL List Job Log API)
有時候系統本身的 System Job (以 Q 開頭的 Job)會寫某些通知性質的訊息至 Job Log, 但
並未將該訊息寫至 QSYSOPR message queue 或 System Log, 所以有時候系統管理人員並無法
得知需要的訊息, 如有可能需要知道誰透過ODBC, OLEDB 或 JDBC 連線進入系統, 要取
得這些資訊可以藉由 Exit Program 或利用 檢查 Job log 的方式. 這裡我僅利用檢查 Job log
的方式完成檢查 MSGID CPIAD02.
File : QRPGLESRC
Member: CHKJOBLOGR
Type : RPGLE
Usage : CRTBNDRPG CHKJOBLOGR
OS version : V5R1(but also can modify to V4R5 earlier for
%LOOKUP bulid-in function to LOOKUP opcode)
H DFTACTGRP(*NO) ACTGRP(*CALLER) BNDDIR('QC2LE') EXPROPTS(*RESDECPOS)
H DATFMT(*ISO) TIMFMT(*ISO) OPTION(*NODEBUGIO) DEBUG
*----------------------------------------------------------------
* CHKJOBLOG Check specified job's job log
* Copyright (C) 10/02/2002 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 all log
* to QSYSOPR message queue, you could modify for checking message
* type or message id to archive yourself purpose.
*----------------------------------------------------------------
* 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('CHKJOBLOG QTEMP ')
D msgtxt s 256
D QUSLIB s 10
D MsgIdDs Ds
D MsgIdEntSize 4B 0
D MsgIdEntStr 7 Dim( 20 )
*Array for contain MsgIdStr
D MsgIdAry S 10 Dim( 20 )
D Inz( *HiVal ) Ascend
D Idx S 2 0
D AryIdx S 2 0
D iMsgId S 7
* -------------------------------------------------------------------
* - 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 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 main PR extpgm('MONJOBLOGR')
D jobname 10
D jobuser 10
D jobnumber 6
Db like(MsgIdDs)
D tomsgq 20
D main PI
D jobname 10
D jobuser 10
D jobnumber 6
D msgIdDsinput like(MsgIdDs)
D tomsgq 20
*----------------------------------------------------------------
C eval msQualifiedJobName = jobname
C eval msQualifiedUserName = jobuser
C eval msQualifiedJobNumber = jobnumber
C eval msgIdDs = msgIdDsInput
C eval msgq = tomsgq
C Eval Idx = 0
C Eval AryIdx = 0
C DoW Idx < MsgIdEntSize
C Eval Idx = Idx + 1
C Eval iMsgId = MsgIdEntStr(Idx)
* only show msgid once
* regardless of number times used.
C If AryIdx = 0 or
C %lookup(iMsgId:MsgIdAry:1:AryIdx) = 0
C Eval AryIdx = AryIdx + 1
C Eval MsgIdAry(AryIdx) = MsgIdEntStr( Idx )
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 '*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 eval uListPtr = uHeadPtr + uOffSetToList
1B C do uNumOfEntrys
C If %lookup('*ALL ':MsgIdAry:1:AryIdx) > 0 or
C %lookup(uMsgId :MsgIdAry:1:AryIdx) > 0
C eval uListPtr2 = uHeadPtr + uOffsetToFlds
C eval msgtxt = 'Job log: ' +
C %trim(jobnumber) + '/' +
C %trim(jobuser) + '/' +
C %trim(jobname) + ' ' +
C uMsgId + ': ' +
C %subst(u2Data:1:U2LengthOfData)
C CALLP QMHSNDM(
C ' ' :
C ' ' :
C %trim(msgtxt) :
C %len(%trim(msgtxt)) :
C '*INFO ' :
C msgq :
C 1 :
C ' ' :
C ' ' :
C vApiErrDs)
C EndIf
C eval uListPtr = uHeadPtr + uOffsetToNext
1E C enddo
C eval *inlr = *on
C return
File : QCMDSRC
Member: CHKJOBLOG
Type : CMD
Usage : CRTCMD CMD(CHKJOBLOG) PGM(CHKJOBLOGR)
/********************************************************************/
/* Title: CHKJOBLOG: Check jobs log */
/* */
/* Description - This command performs job log checked by MSGID */
/* */
/* The Create Command command should include the following: */
/* */
/* CRTCMD CMD(CHKJOBLOG) PGM(CHKJOBLOGR) */
/* */
/********************************************************************/
/*------------------------------------------------*/
/* Command Definition */
/*------------------------------------------------*/
CMD PROMPT('Check Job Log')
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) MAX(20) PROMPT('Message ID to be +
checked')
PARM KWD(TOMSGQ) TYPE(MSGQ) +
PROMPT('Send log to message queue')
MSGQ: QUAL TYPE(*NAME) LEN(10) DFT(QSYSOPR) +
SPCVAL((QSYSOPR)) EXPR(*YES)
QUAL TYPE(*NAME) LEN(10) DFT(*LIBL) +
SPCVAL((*LIBL) (*CURLIB)) EXPR(*YES) +
PROMPT(Library)
星期三, 11月 01, 2023
2002-01-03 如何查知誰更改了系統值 ?
如何查知誰更改了系統值 ?
當某人更改了系統值,系統會送出一個訊息"System value &1 changed from &2 to &3. "
至 System Log, 所以可以藉由指令
DSPLOG OUTPUT(*PRINT) MSGID(CPF1805 CPF1806 CPF1815)
DSPSPLF FILE(QPDSPLOG) SPLNBR(*LAST)
檢視報表即可查知誰於何時改了系統值。
訂閱:
文章 (Atom)