Wednesday, February 24, 2021

Which IBM commands have been changed?

find changed ibm i commands

Someone asked me how to detect if any of their system commands have been changed. By "system commands" they meant any of the commands in the library QSYS. I can think of two ways to do this, and I will describe both below.

I have written before about how to retrieve the defaults of a command, so I will not repeat that here.

When I tested both methods in the IBM i partition I use when writing these posts I found that only one command was returned as changed, therefore, the results I am going to show will be limited to that one command.

 

Has command's defaults changed? Using SQL

I think this method is only available to people using newer releases of IBM i, 7.3 and 7.4, and with the more recent Technology Refreshes. The Object Statistics table function, OBJECT_STATISTICS has been enhanced a lot in recent TRs, adding many new columns to the results. Two of these additions are:

  • APAR_ID
  • USER_CHANGED

The default values for these two columns for an unchanged command is the APAR id to be null and the User changed flag to be '0'.

When a command is changed, using the Change Default command, CHGDFT, or the Change Object Description API, QLICOBJD, the columns are updated. APAR id will now contain 'CHGDFT' and User changed flag will be '1'.

For this example if I wanted to see which, if any, commands had been changed in QSYS library I would use the following statement:

01  SELECT OBJNAME,APAR_ID,USER_CHANGED
02    FROM TABLE(QSYS2.OBJECT_STATISTICS('QSYS','CMD'))
03   WHERE APAR_ID = 'CHGDFT' ;

Line 1: I want the following information returned to me:

  • OBJNAME:  Object name
  • APAR_ID:  APAR id
  • USER_CHANGED:  User changed flag

Line 2: These are the parameters passed to the table function. The first is the name of the library. The second is the object type. I could have used '*CMD', but I chose just to use 'CMD'. The results retuned from this function will be a list of all the commands in QSYS library.

Line 3: But I do not want all commands. I just want those that have changed. With this Where clause I select only those results where the APAR id is 'CHGDFT'.

The results show the changed command:

OBJNAME  APAR_ID  USER_CHANGED
-------  -------  ------------
CRTLIB   CHGDFT   YES

If I just wanted to check whether one command had changed I would change my SQL statement to be:

01  SELECT OBJNAME,APAR_ID,USER_CHANGED
02    FROM TABLE(QSYS2.OBJECT_STATISTICS('QSYS','CMD','CRTLIB')) ;

Line 2: The third parameter is the name of the object.

There is no longer a need for a Where clause.

The result is the same as before.

 

Has command's defaults changed? Not using SQL

This becomes a two-step process. First I need to make a list of all the commands in QSYS library using the Display Object Description command, DSPBJD.

DSPOBJD OBJ(QSYS/*ALL) 
          OBJTYPE(*CMD)
          DETAIL(*FULL)
          OUTPUT(*OUTFILE)
          OUTFILE(QTEMP/@DSPOBJD)

Then I need to look in the output file, @DSPOBJD, for the two fields:

  • ODAPAR:  APAR id
  • ODUMOD:  User modified flag

What tool do I use to access the data from the output file?

I could use something as simple as the Run Query command, RUNQRY, and select any object that is a command and where the APAR id is 'CHGDFT'.

RUNQRY QRY(*NONE) QRYFILE((QTEMP/@DSPOBJD)) RCDSLT(*YES)


                                Select Records

Type comparisons, press Enter.  Specify OR to
  Tests:  EQ, NE, LE, GE, LT, GT, RANGE, LIST,

AND/OR  Field             Test   Value (Field,
        ODOBTP            EQ     '*CMD'         
 AND    ODAPAR            EQ     'CHGDFT'     

But the results shows all the columns.

I know I said this was the "Not using SQL" method, but I meant gathering of the data not to use SQL. I can display what I want and in the format I want with this SQL statement:

01  SELECT ODOBNM,ODAPAR,ODUMOD
02    FROM QTEMP.@DSPOBJD
03   WHERE ODOBTP = '*CMD'
04     AND ODAPAR = 'CHGDFT' ;

Line 1: Display Object name, APAR id, and User modified flag.

Lines 3 and 4: Only include in the results any object that is a command and the APAR id is 'CHGDFT'.

The results look the same as the one from OBJECT_STATISTICS:

ODOBNM  ODAPAR  ODUMOD
------  ------  ------
CRTLIB  CHGDFT  1

 

I have to admit I do not know how to tell which parameters changed and what was the original value of those parameters. If you do know how to determine that please post in comments below.

 

This article was written for IBM i 7.4, and should work for some earlier releases too.

6 comments:

  1. Thank you - getting ready to do an upgrade in a few weeks and always wondered which commands I've changed. Will add this gem to my checklist of things to do afterwards. I appreciate this.

    ReplyDelete
  2. Had a few projects get taken by surprise by this years ago.

    ReplyDelete
  3. I make it a rule to create a CL program that includes all the changes to IBM objects that you can run after an upgrade. Include any CHGCMDDFT commands as well as any other changes to IBM objects such as authority changes. That said, this is a good query to run to validate that nothing got missed.

    ReplyDelete
  4. You should never change defaults on commands in QSYS. Better to duplicate the command to a separate library, put that library on the system library list, and change the default there.

    Also, some third party products depend on certain command defaults in QSYS.

    When I worked on a change control product, a standard part of our diagnostic was to determine if any commands we used had their defaults changed in QSYS.

    ReplyDelete
  5. Interestingly, I looked for a way to figure out if by chance someone changes the cmddft (for example from a ptf) and I found to use the exit linked to the QIBM_QCA_RTV_COMMAND object But I can’t find usable examples
    https://www.ibm.com/docs/en/i/7.3?topic=program-changing-cl-command-defaults
    "You can track changes you make to CL command defaults for use when you install a new release. To track changes, register an exit program for exit point QIBM_QCA_RTV_COMMAND. The exit program is called when you run the CHGCMDDFT command. One of the parameters passed to the exit program is the command string that is being run. You can save the command string to a source file and then compile the source file into a CL program. Finally, you use this program to reproduce the changes you have made to command defaults during the previous release."

    ReplyDelete

To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.

Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.