Migrating an ADCD z/OS release to the next release: OMVS

Start here:Migrating an ADCD z/OS release to the next release.

There are several parts to migrating OMVS.

  • Making your user file systems available to the new level of z/OS
  • Making data from your old system file systems available to the new level of z/OS. Files I updated and copied include
    • /etc csssmtp.env this is used in the mail protocol procedure CSSMTP
    • /etc/hosts this is used in TCPV4 name query lookup
    • /etc/pkiserv/… for the PKI Server for managing digital certificates
    • /etc/resolv.conf this is used in TCPIP DNS
    • /etc/gskssl/… for system ssl.
    • /etc/syslog.conf for managing the SYSLOGD daemon, and where (TCPIP) Unix tasks write their output in the file system
    • /etc/zexpl/… for use with RSEAPI procedure, and z/OS Explorer
  • Copying any customisation from the old system to the new system. This should be in the /etc directory, or in the JCL procedures.
  • Checking your overall OMVS configuration is consistent

The ZFS for /etc is ZFS.S0W1.ETC. This is the same on the Z31A, and the Z25D systems, so cannot you use both copies on the same system. This means you need to use backup and restore; or copy the files to a ZFS which can be used on both systems.

Making your user file systems available to the new level of z/OS

This should just be a matter of making sure your BPXPRMxx with your mount statements is used in the new system, and IPLing with the correct IEASYS member.

HFS is not supported on z/OS 3.1 so you will need to migrate these to ZFS before you try to migrate; and remove and HFS definition statements.

Making your old system file systems available to the new level of z/OS.

On the old system I found all the files I had changed in /etc, and backed them up to a PAX file. I could have copied the directories to a user ZFS file system.

The potential directories of interest are

  • /etc this has configuration files for system tasks such as syslogd
  • /var this contains log files etc as used by system tasks. You usually do not want to copy the files across.
  • /opt program product information which you usually do not want to copy across

How do you find changed files?

See How do I diff on Z/OS with Unix files and directories for a full description.

You can use the command ls -ltr . to list files in the current directory, with the latest changes at the bottom of the list. Or you can use the find command

find . -mtime -100 -a -type f

which lists the files within the last 100 days (-mtime -100); -mtime 100 is exactly 100 days ago; -mtime +100 is over 100 days ago. This way is not very helpful. You can say find files newer than ‘this’ file.

You can create an empty file and set the date on it using

touch -t 2401181400 ~/Jan182024.file    

Where the -t value is yymmddhhmm

You can list files changed more recently than this file file using

find . -newer ~/Jan182024.file  -a -type f

This gives you a list of files

You can use a command to do more processing. The following also lists information about the files.

find . -newer ~/Jan182024.file   -a -type f -exec ls -al {} \;   

How to backup files

You can pipe the information from the find command into other commands such as pax. This takes the stream of filenames, and copies the file contents into a PAX fiile.

find . -newer ~/Jan182024.file  -a -type f | pax -W "seqparms='space=(cyl,(30,30))'" -wzvf "//'COLIN.PAX.TEST2'" -x os390

On the other system you can read the pax file and load the files.

How to see what’s in a pax file

You can see what is in the pax file use

pax   -vf "//'COLIN.PAX.TEST2'" 

Note of warning. You should be careful backing up and restoring when using absolute path names. See Oh p*x, I’ve lost my changes.

How to restore the data

pax -rfk  "//'COLIN.PAX.TEST2'"  

Where the -k option means do not overwrite.

Checking your overall OMVS configuration is consistent

You can use the D OMVS,PFS command to display the in use physical file systems. Issue this command on both old and new systems, and compare the output

z/OS 2.5D D OMVS,PFS output

The -FS GFSCINIT data is for an HFS file system. You need to remove any FILESYSTYPE TYPE(HFS) ENTRYPOINT(GFSCINIT) … entries from systems before using z/OS 3.1

OMVS     0010 ACTIVE             OMVS=(TC,00,01,BP,IZ,RZ,BB,ZW,US)                               
PFS CONFIGURATION INFORMATION
PFS TYPE ENTRY ASNAME DESC ST START/EXIT TIME
-FS GFSCINIT N/A U 2024/08/29 12.56.04
INET EZBPFINI N/A SOCKETS I
-FS GFSCINIT N/A U 2024/08/29 12.56.03
ZFS IOEFSCM N/A LOCAL A 2024/08/29 12.55.59
AUTOMNT BPXTAMD N/A LOCAL A 2024/08/29 12.55.59
UDS BPXTUINT N/A SOCKETS A 2024/08/29 12.55.59
CINET BPXTCINT N/A SOCKETS A 2024/08/29 12.55.59

PFS TYPE DOMAIN MAXSOCK OPNSOCK HIGHUSED
UDS AF_UNIX 10000 2 2
CINET AF_INET6 50000 4 4
AF_INET 64000 8 9

SUBTYPES OF COMMON INET
PFS NAME ENTRY START/EXIT TIME STATUS FLAGS
TCPIP EZBPFINI 2024/08/29 12.56.24 ACT SC
TCPIP2 EZBPFINI INACT
TCPIP3 EZBPFINI INACT
TCPIP4 EZBPFINI INACT

z/OS 3.1A D OMVS,PFS output

Note the missing entry for -FS GFSCINIT.

OMVS     0010 ACTIVE             OMVS=(TC,00,01,BP,IZ,RZ,BB,ZW,US)      
PFS CONFIGURATION INFORMATION
PFS TYPE ENTRY ASNAME DESC ST START/EXIT TIME
INET EZBPFINI N/A SOCKETS I
ZFS IOEFSCM ZFS LOCAL A 2024/08/29 13.00.24
AUTOMNT BPXTAMD N/A LOCAL A 2024/08/29 13.00.24
UDS BPXTUINT N/A SOCKETS A 2024/08/29 13.00.24
CINET BPXTCINT N/A SOCKETS A 2024/08/29 13.00.24

PFS TYPE DOMAIN MAXSOCK OPNSOCK HIGHUSED
UDS AF_UNIX 10000 2 3
CINET AF_INET6 50000 4 4
AF_INET 64000 8 8

SUBTYPES OF COMMON INET
PFS NAME ENTRY START/EXIT TIME STATUS FLAGS
TCPIP EZBPFINI 2024/08/29 13.01.05 ACT SC
TCPIP2 EZBPFINI INACT
TCPIP3 EZBPFINI INACT
TCPIP4 EZBPFINI INACT

Migrating an ADCD z/OS release: ZFS files.

Start here:Migrating an ADCD z/OS release to the next release.

For background see Should I use tar or pax to backup my Unix files?

System files

If you have done any configuration to products which use Unix services, you are likely to have changed files in the file system. For example /etc/syslog.conf.

Configuration files

Many configuration files are configured in the /etc directory.

If you want to find which files have been changed since you have been using the system you could use the ls -ltr command to display the files in each directory, displayed with the latest changed date at the bottom.

This gets very tedious when you have a lot of directories to example. However you can ask Unix to list all files which match a critera, such as changed in the last n days, or newer than an existing file.

Create a file of the comparison data

touch -t 202202211456 /tmp/foo

This creates a file /tmp/foo with the given date year 2022 month 02 date 21 time 1456

find . -type f -newer /tmp/foo |xargs ls -ltr > aa

This is two commands.

  • The find command
    • looks in the current directory (.) and subdirectories
    • for objects with type of files (rather than directories etc)
    • which have been changed more recently than /tmp/foo.
  • The file name is passed to the ls -ltr command to display the date time information.
-rwx------   1 OMVSKERN OMVSGRP       32 Feb 13  2023 ./cssmtp.env 
-rw-r--r-- 1 OMVSKERN OMVSGRP 3453 Feb 13 2023 ./mail/ezatmail.cf
-rwxr-xr-x 1 OMVSKERN OMVSGRP 250 Feb 28 2023 ./hosts
-rw-r--r-- 1 OMVSKERN OMVSGRP 226441 Jun 16 2023 ./pkiserv/pkiserv.tmpl.old
-rw-r--r-- 1 OMVSKERN OMVSGRP 22406 Jun 16 2023 ./pkiserv/pkiserv.conf.old
...

if you use

find . -type f -newer /tmp/foo |tar -cvf ~/etc.tar –

it will create a tar file containing the changed files. You can then transport the etc.tar file to the newer system and untar it.

You can use the pax command to package the files

find . -type f -newer /tmp/foo |pax -W “seqparms=’space=(cyl,(10,10))'” -o saveext -wzvf “//’COLIN.PAX.TEST'” -x os390

to save the files in pax format into the data set COLIN.PAX.TEST. If the high level qualifier has been defined as an alias is the master catalog on both systems, the data set will be visible on both systems.

Note: If you specify

find . -type d -newer /tmp/foo

It displays all directory entries which have been changed, and displays all the files within those directories.

For example

total 1344 
-rw-r--r-- 1 OMVSKERN OMVSGRP 3252 May 7 2019 ssh_config
-rw-r--r-- 1 OMVSKERN OMVSGRP 553761 May 7 2019 moduli
-rwx------ 1 OMVSKERN OMVSGRP 65 Oct 29 2019 sshd.sh

For example the sshd directory was changed in September this year, so all the files below it are listed. 

Application output files

These are usually in the /var sub-directory. You may not need to move these files across.

User data

You will have your own data in the Unix file systems. If you put the data under the /u file system it should be easy to find! 

You may have configured userids so their home directory is on a “user” ZFS file system, or your home directory could be mixed in with the systems files. For example the file system for IBMUSER is on an ADCD file system (D5USS2).

IBMUSER:/S0W1/etc: >df -P ~                                                         
Filesystem 512-blocks Used Available Capacity Mounted on
ZFS.USERS 2880000 1277970 1602030 45% /u

The newer system also has a ZFS.USERS. You cannot have both old and new ZFS.USERS mounted at the same time, as the mount takes cataloged data set.

For my application data

IBMUSER:/S0W1/etc: >df -P /u/tmp
Filesystem 512-blocks Used Available Capacity Mounted on
COLIN.ZFS2 2817120 788338 2028782 28% /u/tmp

I can take this ZFS system and mount it on the newer system.

You can tar up the files under a directory and move the tar file to the new system, or you can use pax which I think is better, as it creates a dataset out of the ZFS files.

Using tar

Note: if you use an absolute path in the tar command, when you untar the data it will use the same directory- – which may overrwrite data you wanted to keep.

If you use are relative directory, the data is untarred relative to the current directory.

cd /u/colin
tar -cvf ~/relative.tar *

is better than

tar -cvf ~/absolute.tar /u/colin

On the new system if I use

mk dir oldcolin
cd oldcolin
tar -xtvf relative.tar

it will restore the files in oldcolin.

If I use

mk dir oldcolin
cd oldcolin
tar -xtvf absolute.tar *

it will restore the files to /u/colin – and overwrite any files which were there.

What directories were created?

You can use the command

find /u -type d -newer /tmp/foo |xargs ls -ltrd> aa

to display the directories created/modified since the time of the /tmp/foo file.

This gives output like

drwxrwxrwx  10 OMVSKERN SYS1        8192 Dec  8 13:04 ./adcd 
drwxr-xr-x 2 OMVSKERN 1000 8192 Mar 15 2023 ./tmp/oemput
drwxrwxrwx 2 OMVSKERN WEBGRP 8192 Apr 25 2023 ./mqweb3/logs
drwxr-xr-x 2 OMVSKERN SYS1 8192 Jun 16 2023 ./mqweb2/oldconf

You can use the pax -E option to display the contents and extended attributes.

pax -E -f "//'COLIN.PAX.HTTP2'"

Notes the double / and both sets of quotes.

To unpax the files on the new system, cd into the directory and use

pax -k -rvf  "//'COLIN.PAX.TEST'" .

The

  • -k means do not overwrite
  • -r read
  • -v display the details
  • -f from the following file
  • into . (the current directory)

To mount a ZFS on the system

You can have an entry in an BPXPRMxx parmlib member, so a ZFS is mounted at IPL time.

You can also use a TSO command, or a batch job to mount a ZFS

//IBMMFAMO JOB 1,MSGCLASS=H
//MOUNT EXEC PGM=IKJEFT1A
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *
MOUNT FILESYSTEM('AZF220.ZFS') TYPE(ZFS) +
MOUNTPOINT('/u/mfa') +
MODE(RDWR) PARM('AGGRGROW') AUTOMOVE

Sharing File systems

You can display the mounted file systems using the D OMVS,F command

This gives output like

ZFS            16 ACTIVE                      RDWR  01/15/2024  L=30  
NAME=ZFS.USERS 14.38.54 Q=0
PATH=/u
OWNER=S0W1 AUTOMOVE=N CLIENT=N
ZFS 37 ACTIVE RDWR 01/15/2024 L=48
NAME=COLIN.ZFS2 14.38.56 Q=0
PATH=/u/tmp
OWNER=S0W1 AUTOMOVE=Y CLIENT=N

This shows there are two ZFS file systems, both mounted read/write. The first has

  • data set name ZFS.USERS. On the z24C system – this is the z24C file system. You cannot mount both the z24C, and the z25D file systems at the same time, because the mount command uses the cataloged data set.
  • mounted as path /u

The second has

  • data set name COLIN.ZFS2
  • mounted as path /u/tmp

You can choose to mount your data under an existing path, or create a new tree such as “/my”.

Migrating an ADCD z/OS release to the next release: Parmlib members

Start here:Migrating an ADCD z/OS release to the next release.

The ADCD supplied parmlib members may change from release to release, for example the volser of disks will change from D5SYS1 to A3SYS1.

Some of the parmlib members you create, in USER.*.PARMLIB, may not be compatible with the new version, for example you explicitly refer to Z25D data sets, and the new data sets are Z31A data sets.

  • You need to compare the new ADCD supplied parmlib, with your current ADCD parmlib, and check there are no surprise.
  • You need to review your current user parmlib. You should be able to parameterise your library, for example using &SYSVER. instead of Z31A or Z25D. You can also identity which members you actually use, and only copy those to the new system.

How to see the new ADCD libraries on the old system.

I used ISPF 3.4 with prefix ADCD on volser A3SYS1, then used the local command C to catalog the data sets of interest (including CLIST, PARMLIB, and PROCLIB) . Once cataloged you can use ISPF 3.4 and specify ADCD.*.PARMLIB to list them both

How to find what parmlib members you use

In your old system, look at the joblog. Start from the start of IPL message IEE042I SYSTEM LOG DATA SET INITIALIZED.

After this, you get messages like

IEE252I MEMBER IEASYM00 FOUND IN USER.Z25D.PARMLIB

On my old system, I used SDSF S.;STATUS for JOBNAME SYSLOG. You can use the SE prefix command to edit the syslog file. I used X ALL;F IEE252I ALL;DEL ALL X to show all of the parmlib members used.

I made a backup of the parmlib, and deleted the parmlib members which were not used, so the user….parmlib contained only the definitions I needed.

I IPLed the system to make sure they worked.

I used the ISPF command SRCHFOR on the user parmlib , and user proclib, to search for Z25D (the release I was running), and changed all values to &SYSVER. When you IPL with a different version of z/OS the value of the &SYSRES for the new system, will be used.

As part of the clean up you may want to compare your members with the ADCD provided members for example edit a user….parmlib member and use the ISPF command COMPARE ‘adcd.z25D.parmlib(…)’ exclude to see the difference.

You can compare members in a PDS see How do I compare two PDS on z/OS.

You might want to see if your user… members can be deleted as they are the same as provided by ADCD.

You can look at the dates on the members, and you only need to check members with a “recent” date (since you got the system).

Parmlib changes

Some of of the my parmlib members changed include

  • AUTOR… for automatic replies to z/OS messages
  • BPXPRM to mount my OMVS file systems.
  • CLOCK00 to change the time zone to E.00.00.00 ( GMT)
  • CSFPRM for ICSF
  • IEASYM00 to add symbols used by TCPIP
  • IEASYM00 with my IPL changes
  • IGDSMS00 to add PDSE… and PDSE1… definitions
  • IKJTSO00 to add entries for ICSF panel processing. CSFDPKDS and CSFDPKDS
  • IRRPRM to put the definitions of the RACF database into parmlib
  • PFKTAB00 to change the default PF keys on the console
  • PROGxx members for APF and LNKLIST
  • SCHED

ReIPL the new system and check there are no unexpected messages. You can IPL your old system to fix the problems.

Copy your parmlib members

You can copy your parmlib members from USER.Z25D.PARMLIB to USER.Z31D.PARMLIB.

Update SYS1.IPLPARM

You need to update SYS1.IPLPARM (on A3SYS1) to add and entry for the load parm you use.

I copied LOAD00, and used

SYSPARM CP
IEASYM (00,CP)

This will use USER…PARMLIB(IEASYSCP), and will use the ADCD provided IEASYM00, and my IEASYMCP in USER…PARMLIB

IPL the new system

I used

ipl 0ac8 parm 0acfCP

to use the member LOADCP in SYS1.IPLPARM

Migrating an ADCD z/OS release to the next release: Proclib members

Start here:Migrating an ADCD z/OS release to the next release.

The ADCD supplied proclib members may change from release to release, for example the volser of disks will change from D5SYS1 to A3SYS1, and you may have a copy in user…proclib which overrides the ADCD supplied members.

What is different between your USER.Z25D.PROCLIB and ADCD.Z25D.PROCLIB?

It is good practice to see what you have changed in the USER.*.PROCLIB.

Use ISPF 3.4 to look at ADCD.Z25D.PROCLIB, display the members, and sort on changed. If you were careful you have not changed anything in this library, but made your changes in USER.Z25D.PROCLIB.

Compare USER.Z25D.PROCLIB and ADCD.Z25D.PROCLIB

You can use ISPF 3.13, the SuperCE utility to compare the members.

I specified

  • New DS Name . . . ‘USER.Z25D.PROCLIB’
  • Old DS Name . . . ‘ADCD.Z25D.PROCLIB’
  • Compare Type 2
  • Listing Type 2

There are several sections to the output

  • Changes between members found in both libraries
  • CHNG MEMBERS-COMPARED and which members were common, and how many lines different there were
  • NON-PAIRED NEW FILE MEMBERS (files only in USER.Z25D.PROCLIB) | NON-PAIRED OLD FILE MEMBERS (files only in ADCD.Z25D.PROCLIB)

For example

...
NEW: USER.Z25D.PROCLIB OLD: ADCD.Z25D.PROCLIB

CHNG MEMBERS-COMPARED NEW-PROC OLD-PROC MATCHED NEW-INS OLD-DEL

** CSF 2 5 0 2 5
** FTPD 16 14 12 4 2
** HZSPROC 42 42 41 1 1
** TCPIP 14 71 10 4 61
** VTAM00 7 6 6 1 0

5 TOTAL MEMBER(S) PROCESSED AS A PDS
5 TOTAL MEMBER(S) PROCESSED HAD CHANGES
0 TOTAL MEMBER(S) PROCESSED HAD NO CHANGES
11 TOTAL NEW FILE MEMBER(S) NOT PAIRED
281 TOTAL OLD FILE MEMBER(S) NOT PAIRED
NON-PAIRED NEW FILE MEMBERS | NON-PAIRED OLD FILE MEMBERS
AZF#IN00 | ASMAC
AZF#IN01 | ASMACG
BACKUP | ASMACL
... | ...

Once you understand the changes between the USER.Z25D.PROCLIB and ADCD.Z25D.PROCLIB, you can do a similar exercise between USER.Z25D.PROCLIB and ADCD.Z31A.PROCLIB

The changes I had made to USER.*.PROCLIB include

Specifying a PRM to ICSF in member CSF

//CSF  PROC PRM=CP                                                       
//CSF EXEC PGM=CSFINIT,PARM=&PRM,REGION=0M,TIME=1440,MEMLIMIT=NOLIMIT

This uses the CSFPRMCP in the Parmlib concatentation.

This had

CKDSN(COLIN.SCSFCKDS) 
PKDSN(COLIN.SCSFPKDS)
TKDSN(COLIN.SCSFTKDS)
DOMAIN(0)

COMPAT(NO)
SSM(NO)
CHECKAUTH(NO)
CTRACE(CTICSF00)
USERPARM(USERPARM)
REASONCODES(ICSF)

Health Checker HZSPROC

This had //HZSPROC PROC HZSPRM=‘(AD,US)’ instead of //HZSPROC PROC HZSPRM=’AD

Where USER.Z25D.PARMLIB(HZSPRMUS) has

ADDREPLACE POLICY STATEMENT(COLINS) 
UPDATE CHECK(IBMRACF,RACF_SYSPLEX_COMMUNICATION)
DATE(20240120)
INACTIVE
REASON('COLIN - Test/Development env')

ADDREPLACE POLICY
UPDATE CHECK(IBMRACF,RACF_PROTECTALL_FAIL)
DATE(20240120)
INACTIVE
REASON('COLIN2- do not want in one person system')

ADDREPLACE POLICY
UPDATE CHECK(IBMXCF,XCF_TCLASS_CLASSLEN)
DATE(20240120)
INACTIVE
REASON('COLIN - NON sysplex no xcf message buffers ')

to prevent unnecessary health check messages from being produced.

TCPIP

  • Remove the TSO step with RACFCRT CRTHOST_.
  • Remove the comments
  • Change the PROFILE
  • Change the SYSTCPD statement.

FTPD

VTAM00

This procedure issues commands as part of the z/OS start up. It executes commands in parmlib member VTAM00

Add DSN=USER.&SYSVER..PARMLIB(&M),DISP=SHR to the parmlib definition

My USER.Z31A.PARMLIB(VTAM00) has

* Make the operator console nice
K A,NONE,L=L700
* FOR HEALTH CHECK MESSAGE
$T CKPTDEF,OPVERIFY=NO

How do I diff on Z/OS with Unix files and directories

I wanted to compare the contents of two directories in Unix System Services on z/OS before I merged them. This took me some time to do because the documented is lacking.

With ISPF you can use SUPERC (3.13), give it two PDSs and it shows you the differences.

On Unix there is the diff command. This can compare individual files, or directories. It can display just the changes, or the changes in context.

File a

AOnly 
line1
Aline2
line3

File b

line1 
Bline2
line3
BOnly
BOnly2

Using ispf edit compare to show differences

You can use diff to show the differences in two files, but it is not easy to understand. ISPF EDIT has the compare facility. If you know two files are different you can use

  • oedit /etc/zexpl/rseapi.env
  • use the primary command compare
    • enter the fully qualified name /u/ibmuser/zexpl/rseapi.env,, in the “Name . . . . .” field. if you specify +/filename the + means the same directory.
    • press pf3 and it will show the differences

Because I tend to remove comments to make it easier to see the content, I tend to use

  • oview /etc/ssh/sshd_config you get into ISPF edit, but no changes are saved.
  • Comments start with a #. x all;f ‘#’ all 1 1; f ‘ ‘ 1 1 all;del all nx removes comment lines and blank lines
  • reset to show the hidden lines
  • compare I then specify my version of the file, and see the changes.

  • Lines like ====== TrustedUserCAKeys /etc/ssh/user_ca_key.pub are from my copy.
  • Lines in green with a line number are in both files 000006 Subsystem sftp /usr/lib/ssh/sftp-server
  • Lines like .OAAAA UseDNS yes are from the base file

Update your version, make a copy of the original, then replace the original with your version.

diff -c1 a b – show the files and the changes in context

The line prefix for input file going to output file

  • – to be removed
  • ! to be changed
  • + to be added

The command diff -c1 a b gives

*** a Tue Aug 27 02:48:56 2024              
--- b Tue Aug 27 02:50:41 2024
***************
*** 1,4 ****
- AOnly
line1
! Aline2
line3
--- 1,5 ----
line1
! Bline2
line3
+ BOnly
+ BOnly2
  • *** a Tue Aug 27 02:48:56 2024 the first file name, and last changed date
  • — b Tue Aug 27 02:50:41 2024 the second file name, and last changed date
  • *** 1,4 **** the*** show it is file 1, lines 1 to 4
  • – AOnly this line is in file a is not in file b, so would need to be removed(-) from file a
  • ! Aline2 this line is in file b – but different
  • — 1,5 —- this is file b, lines 1 to 5
  • ! Bline2 this line is also in file a – but different
  • + BOnly this line is in file b and and was additional(+) to file a

When one file exists but is empty you get output like

*** /etc/resolv.conf Wed Mar  6 11:54:50 2024                         
--- /u/ibmuser/temp/resolv.conf Thu Dec 7 05:40:24 2023
***************
*** 0 ****
--- 1,2 ----
+ nameserver 127.0.0.1
+ TCPIPJOBNAME TCPIP

which follows the rules I explained above. *** 0 **** shows the content after line 0 is empty, because the next line is — 1,2 —- from the other file.

diff a b – show just the changes

gives

1d0             
< AOnly

3c2
< Aline2
---
> Bline2

4a4,5
> BOnly
> BOnly2

The output can be split into sections. The first line of each section is like

  • 1d0 the first line of a needs to be deleted from b, line 0
  • 3c2 line 3 of a is changed from line 2 of b
  • 4a4,5 lines 4,5 of b need to be added to a

The < and > tell you which file the data came from

When data is changed it gives the lines

  • < content of file a
  • output divider
  • > content of file b

When the data is in file a and not file b

  • < contents of file a

When the data is in file b and not file a

  • > contents of file b

diff -s dir1 dir2 compare the directory contents

If you specify -s, or just specify two directories, it compares the directory content.

You can use

diff -c1 dir1 dir2 

the -c1 to display the contents (how I like it).

With the directory entries you get records like

Only in /u/ibmuser/temp: test.tar 
Common subdirectories: /etc/wbem and /u/ibmuser/temp/wbem
Only in /etc: yylex.c
diff -c1 /etc/hosts /u/ibmuser/temp/hosts
*** /etc/hosts Wed Mar 6 11:06:55 2024
--- /u/ibmuser/temp/hosts Tue Feb 28 12:43:07 2023

You can find which files are missing from /etc , by using grep ‘Only in /u/ibmuser/temp’ on the output.

It shows the command used for the individual files, and the output

diff -c1 /etc/hosts /u/ibmuser/temp/hosts
*** /etc/hosts Wed Mar 6 11:06:55 2024
--- /u/ibmuser/temp/hosts Tue Feb 28 12:43:07 2023
...

diff -s -r dir1 dir2 compare the directory contents

The -r option displays the data recursively.

How do I change all members of a PDS? Easy – use an edit macro

I looked on the internet, to find something that would allow me to make the same change to all members of a PDS, and there seemed to be several options, IPOUPDTE, CPPUPDTE, PDSUPDTE, written in assembler many years ago.

I had written an equivalent program in C, but I no longer have the source. I found it as quick to write a solution using Rexx and an ISPF edit, than to find a solution on the internet. The solution is much more flexible, and can do so much more.

The processing has two stages

  • Code to iterate over each member of the PDS, and invoke ISPF EDIT on each member
  • An edit macro to make the changes.

Code to iterate over each member

ISPF 3.4 DSLIST displays data sets

DSLIST - Data Sets Matching COLIN.J*       
Command ===>

Command - Enter "/" to select action
-------------------------------------------
AA COLIN.JCL
COLIN.JCL.DCOLLECT.OUTPUT

You can enter local commands at the front of each line. The commands can be ISPF special (D for Delete, C for Catalog, R for Rename), or TSO commands, where a TSO command can be a Rexx exec in the ISPEXEC concatenation. (You can use the TSO ISRDDN command to display the data sets allocated to your session)

I have a Rexx exec called AA.

Access the parameters passed to the rexx

/* rexx */                                           
ADDRESS ISPEXEC "VGET (ZDLDSN) SHARED"
ADDRESS ISPEXEC "VGET (ZDLCMD) SHARED"
ADDRESS ISPEXEC "VGET (ZDLLCMD) SHARED"
say "ZDLDSN " ZDLDSN
say "ZDLCMD " ZDLCMD
say "ZDLLCMD " ZDLLCMD

With the line command

Command - Enter "/" to select action  
--------------------------------------
AA 99 COLIN.JCL

The Rexx produces

ZDLDSN    COLIN.JCL
ZDLCMD AA 99
ZDLLCMD AA 99 'COLIN.JCL'
  • ZDLDSN is the data set name
  • ZDLCMD is the line command and any data
  • ZDLLCMD is the (Long) combined command and the data set

With the line command

aa 99 / Zyx

The dataset name is substituted for /, and the output is

ZDLDSN    COLIN.JCL
ZDLCMD AA 99 / Z
ZDLLCMD AA 99 'COLIN.JCL' Zyx

This means you can pass parameters to your Rexx.

Process every member

The data set name is in variable ZDLDSN. When you use it, you should quote it because your userid may/may not have prefix on, which puts your userid on the front of every data set you use. Without quotes, it could not find dataset COLIN.COLIN.JCL

  • The LMINIT command returns a handle in the DATAID(handle) variable, to refer to the data set. My handle is called data1.
  • The LMOPEN command opens the dataset associated with the handle.
  • The LMMLIST command iterates through the list, starting with a blank member name which indicates start with the first.
  • The EDIT command invokes ISPF edit on the member, and passes the name of an ISPF EDIT macro to use. In my case the macro is called FOREACH.
Address ispexec "LMINIT DATAID(data1) dataset('"ZDLDSN"')" 
if rc <> 0 then
do /* report the errors */
say ZERRSM ZERRLM
return 8
end
Address ispexec 'LMOPEN DATAID('data1') OPTION(INPUT)'
member = ' '
lmrc = 0
/*********************************************************************/
/* Loop through all members in the PDS, issuing the EDIT service for */
/* each. */
/*********************************************************************/
Do i = 1 by 1
Address ispexec 'LMMLIST DATAID('data1') OPTION(LIST),
MEMBER(MEMBER) STATS(NO)'
If rc = 8 then leave /* not found */
If rc <> 0 Then
do
say ZERRSM ZERRLM
leave
end
else
do
Address ispexec 'EDIT DATAID('data1') MEMBER('member')
MACRO(FOREACH)'
end
End
/*********************************************************************/
/* Free the member list and close the dataid for the PDS. */
/*********************************************************************/
Address ispexec 'LMMLIST DATAID('data1') OPTION(FREE)'
Address ispexec 'LMCLOSE DATAID('data1')'
Exit 0

From the information passed to the Rexx exec, you could pass the edit macro as a parameter, such as

AA / MYMAC 

I was just lazy and hard coded the macro name.

An edit macro to make the changes

My basic macro just reports the member name, and the size of the file

ADDRESS ISPEXEC 'ISREDIT MACRO' 
"ISREDIT (last) = LINENUM .ZLAST"
"ISREDIT (member ) = MEMBER"
"ISREDIT (curr,orig,concat)= DATASET"
say "foreach " member last curr
"ISREDIT END"
  • The LINENUM command returns the line number of the specified line. You can create your own line labels. ISPF provides .ZFIRST and .ZLAST .ZCSR (the line where the cursor is currently.
  • The MEMBER command returns the member name
  • The DATASET command returns the current name of the dataset (and other information)

You can now do conditional processing, if the data set name starts with… then change…; if the member name starts with… then change…

You can use standard ISPF commands for example

/* */ 
/* trace e */
ADDRESS ISPEXEC 'ISREDIT MACRO'

"ISREDIT X ALL "
"ISREDIT FIND '//' ALL"
"ISREDIT CHANGE 'IBMUSER' 'COLIN' 1 10 ALL NX"
return
"ISREDIT END"

Without the return statement in the code, the code makes the changes and exits, it invisibly edits all of the members. With the return statement this gives you the opportunity to review the changes and to use end or cancel to leave the edit session.

Whoops – what happened there

To test the macros I use ‘view’ of the member, to edit it, but not save any changes. I then executed the macro.
I was trying to change a VOLSER to a symbol.

/* */ 
ADDRESS ISPEXEC 'ISREDIT MACRO'
"ISREDIT (member ) = MEMBER"
say member
"ISREDIT SCAN OFF"
if substr(member,1,6) <> "IEASYM" then
do
"ISREDIT CHANGE 'A3PRD1' '&&SYSP1.' ALL "
"ISREDIT CHANGE 'A3PRD2' '&&SYSP2.' ALL "
"ISREDIT CHANGE 'A3PRD3' '&&SYSP3.' ALL "
"ISREDIT CHANGE 'A3PRD4' '&&SYSP4.' ALL "
"ISREDIT CHANGE 'A3PRD5' '&&SYSP5.' ALL "
"ISREDIT CHANGE 'A3RES2' '&&SYSR2.' ALL "
"ISREDIT CHANGE 'A3SYS1' '&&SYSS1.' ALL "
"ISREDIT CHANGE 'A3CFG1' '&&SYSC1.' ALL "
end
return
"ISREDIT END"f

I wanted to change A3PRD1 to the symbol &SYSP1. I had use use &&, and SCAN OFF. Without these, ISPF treats &SYSP1 as an ISPF symbol, cannot find it, so replaces it with a null.

How do I compare two PDS on z/OS

I am migrating from one ADCD system to a newer version. I wanted to see the differences in the supplied members.

In ISPF 3.13 (SUPERCE) you can compare dataset members.

  • Enter the New DS Name and the Old DS Name
  • If you leave the PDS Member List blank, you get prompted on the next page to select the members of interest. I specified *
  • Compare type 1 (file) gives you a report on the members which are the same or not. See Output from file compare
  • Compare type 2 (line) shows the contents which are different.
    • Listing type 2 (Delta) gives just the changed lines. See here
    • Listing type 3 (CHNG) shows the change in context. See here
    • Listing type 4 (Long) shows the all the members

Output from file compare

                                                                                     
MEMBER SUMMARY LISTING (FILE COMPARE)

DIFF SAME MEMBERS-COMPARED N-BYTES O-BYTES N-LINES O-LINES N-HASH-SUM O-HASH-SUM

** IEASYMCP 400 400 5 5 0EA58F29 0EA58F29
** IEASYMZZ 2000 2000 25 25 2D0DCCA3 2D0DCCA3
** IEASYSCP 800 720 10 9 6D0F7302 737B66E5
** IEASYSC2 800 800 10 10 7B933738 7B933738
** IEASYS00 3760 3760 47 47 61EAEE95 61EAEE95
** IGDSMS00 1920 1920 24 24 A24BDDC8 A24BDDC8
** IKJTSO00 9920 9920 124 124 46049FE2 46049FE2

Output from Line compare, CHNG output(3)

This shows the changes in context.

  • At the front of the line is I or D, to show what was added or deleted
  • The TYPE MAT= is the count of matching lines, and the line numbers within the files.
  • TYPE=RPL is the count of lines replace, and the line numbers within the files.
 NEW: USER.Z31A.PARMLIB(IRRPRMCP)     OLD: USER.Z25D.PARMLIB(IRRPRMCP) 

LISTING OUTPUT SECTION (LINE COMPARE)

ID SOURCE LINES TYPE LEN N-LN# O-LN#
----+----1----+----2----+----3----+----4----+----...
DATABASE_OPTIONS MAT= 3 00001 00001
DATASETNAMETABLE 00002 00002
ENTRY 00003 00003
I - PRIMARYDSN(COLIN.RACFDB.NEW) RPL= 1 00004 00004
D - PRIMARYDSN(COLIN.RACFDB2)
BACKUPDSN(SYS1.RACFDS.BACKUP) MAT= 1 00005 00005

You also get the output from the Output from file compare

Output from Line compare, Delta output(2)

This just gives the inserted and deleted lines. It is a subset of the data above.

NEW: USER.Z31A.PARMLIB(IRRPRMCP)  OLD: USER.Z25D.PARMLIB(IRRPRMCP) 

LISTING OUTPUT SECTION (LINE COMPARE)

ID SOURCE LINES TYPE LEN N-LN# O-LN#
----+----1----+----2----+----3----+----4----+--...
MAT= 3
I - PRIMARYDSN(COLIN.RACFDB.NEW) RPL= 1 00004 00004
D - PRIMARYDSN(COLIN.RACFDB2)

You also get the output from the Output from file compare.

IOS077E IOS075E zPDT ADCD. Fixed!

Update

After I installed ZDT_Install_PE_V14.2.4.tgz. I could use later Linux kernels. This worked on

  • Ubuntu 22.04 with 5.15.0-122-generic
  • and Ubuntu 24.04.1 LTS (GNU/Linux 6.8.0-48-generic x86_64)

The original problem

After an upgrade to my Ubuntu system, I started getting

IOS071I 0405,A1,VTAM, MISSING CHANNEL AND DEVICE END    
IOS071I 0401,A0,VTAM, MISSING CHANNEL AND DEVICE END
IOS071I 0405,**,VTAM, HALT SUBCHANNEL INTERRUPT MISSING
IOS077E 0405,**,*MASTER*, CLEAR SUBCHANNEL INTERRUPT MISSING
IOS075E 0405,RECURRING MIH CONDITION FOR THIS DEVICE
IOS077E 0405,**,*MASTER*, CLEAR SUBCHANNEL INTERRUPT MISSING
IOS075E 0405,RECURRING MIH CONDITION FOR THIS DEVICE
IOS077E 0405,**,*MASTER*, CLEAR SUBCHANNEL INTERRUPT MISSING
IOS075E 0405,RECURRING MIH CONDITION FOR THIS DEVICE

This seems to be a Linux problem.

On Ubuntu uname -a gave me

6.8.0-40-generic #40~22.04.3-Ubuntu SMP PREEMPT_DYNAMIC

I rebooted Linux, interrupted the boot sequence, chose advance boot options for Ubuntu, and chose a different level. Once Linux had restarted uname -a gave me

6.5.0-45-generic #45~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC

and this works with no problems.

Until this is fixed, you’ll have to do this at every reboot. You can specify the default kernel, but it is not well explained, so I’ll go with this method. The fix is due to be shipped in zPDT due 4Q2024.

I found some documentation on saving the last Linux kernel used

The best solution was to set (in /etc/default/grub):

 GRUB_DEFAULT=saved
GRUB_SAVEDEFAULT=true

With this settings the last selected value is kept for the next boot. If you have a new kernel you don’t have to edit your config.

Don’t forget to re-run sudo update-grub

It fails on earlier and current(14.2.2) releases of zPDT code.

How do I test my RACF updates or recover from a boo-boo?

I am running z/OS on zPDT on my Linux server. I want to test out some RACF commands, but want to be able to recover if I get it wrong. What can I do?

The product zSecure Admin offers RACF Offline can be used by those who have the license.

I do not have this product so I need a different way.

I am running a single user z/OS image. For anything more complex than this, talk to the experts.

Background to RACF

RACF has a database, typically SYS1.RACFDS. For availability you can have a backup RACF database, typically SYS1.RACFDS.BACKUP. Typically these are both updated when changes are made to the RACF environment. I would call this a duplexed dataset.

You can make a copy of a RACF database using the RACF utility IRRUT200. This takes a lock on database for the duration of the copy and ensures the copy is consistent. If you use other tools to backup the primary database, and there were concurrent database updates, the backup may not be consistent. You risk a partial update, and an inconsistent database.

Changing your RACF

You can use the RVARY command (TSO and operator) to change the RACF data sets. You can setup controls for the RVARY command.

If you use SETROPTS LIST it will list the RACF options being used. Mine has (near the bottom)

DEFAULT RVARY PASSWORD IS IN EFFECT FOR THE SWITCH FUNCTION.
...
DEFAULT RVARY PASSWORD IS IN EFFECT FOR THE STATUS FUNCTION.

In this case the default password is YES

See SETROPTS RVARY(…)

You will get a prompt

ICH703A ENTER PASSWORD TO SWITCH RACF DATASETS JOB=IBMUSER USER=IBMUSER

If you have an I/O problem with the SYS1.RACFDS database

You can

  • switch to use the backup, and stop duplex updates.
  • fix the problem. Perhaps delete the data set and recreate it on a different device.
  • copy the backup dataset using IRRUT200 to the newly allocated dataset
  • activate the newly allocated dataset activate the duplex updates.

Updates to the RACF database are written to SMF 80 records.

If you make mistakes with your commands

Some RACF command changes you can undo, for example, you can use an alter command to set a new value. To be able to undo the change you need to know what the original value was, so it is always a good idea to display a resource before you change or delete it.

If you delete a record there is no easy way of undoing it.

Rob van Hoboken suggested the following.

Plan A – online switch

Display the status

#rvary list

This gave me

ICH15013I RACF DATABASE STATUS:                          
ACTIVE USE NUM VOLUME DATASET
------ --- --- ------ -------
YES PRIM 1 A3CFG1 SYS1.RACFDS
YES BACK 1 A3CFG1 SYS1.RACFDS.BACKUP

This shows both data sets are active and which is the primary and which ise the backup.

Switch off your RACF DUPLEX (backup) data set

#RVARY INACTIVE,DATASET(SYS1.RACFDS.BACKUP)

It prompts with

ICH702A ENTER PASSWORD TO DEACTIVATE RACF JOB=RACF USER=START1

I didnt know the password, but I replied r xx,YES and it worked!

Run the commands that you hope will work.

If the commands do not work successfully

If the commands do not work successfully, make the backup active and switch to it.

#RVARY ACTIVE,DATASET(SYS1.RACFDS.BACKUP)
#RVARY SWITCH

See the command RVARY (Change status of RACF database) .

After you have switched to the backup, make the primary inactive

#RVARY INACTIVE,DATASET(SYS1.RACFDS)

and copy the backup into the primary using IRRUT200

//IBMUSRAC  JOB 1,MSGCLASS=H                              
//S1 EXEC PGM=IRRUT200 PARM=ACTIVATE
//SYSRACF DD DISP=SHR,DSN=SYS1.RACFDS.BACKUP
//SYSUT1 DD DISP=SHR,DSN=SYS1.RACFDS
//SYSUT2 DD SYSOUT=*
//SYSIN DD *
//SYSPRINT DD SYSOUT=*

First run it without PARM=ACTIVATE. If this works successfully, then use PARM=ACTIVATE, this take a lock during the copy, and then activates the SYSUT1 data set, so both are now active.

This gave the output

IRR62005I - IDCAMS REPRO copied SYSRACF to the work data set SYSUT1                                         
ICH15013I RACF DATABASE STATUS:
ACTIVE USE NUM VOLUME DATASET
------ --- --- ------ -------
YES PRIM 1 A3CFG1 SYS1.RACFDS.BACKUP
YES BACK 1 A3CFG1 SYS1.RACFDS
ICH15020I RVARY COMMAND HAS FINISHED PROCESSING.

The #RVARY LIST gave, as expected

ICH15013I RACF DATABASE STATUS:                                                  
ACTIVE USE NUM VOLUME DATASET
------ --- --- ------ -------
YES PRIM 1 A3CFG1 SYS1.RACFDS.BACKUP
YES BACK 1 A3CFG1 SYS1.RACFDS

Which shows it has worked.

If the commands do work successfully

If the commands do work successfully, you need to bring the backup up to date with the primary.

//IBMUSRAC  JOB 1,MSGCLASS=H                              
//S1 EXEC PGM=IRRUT200,PARM=ACTIVATE
//SYSRACF DD DISP=SHR,DSN=SYS1.RACFDS
//SYSUT1 DD DISP=SHR,DSN=SYS1.RACFDS.BACKUP
//SYSUT2 DD SYSOUT=*
//SYSIN DD *
//SYSPRINT DD SYSOUT=*

The #rvary active command.

I would be careful about using the #RVARY ACTIVE command. If you copy a RACF data set, then use the RVARY ACTIVE command to make it available, there is a small window where changes made to the active RACF data base are not made to the offline one. You could tell people “do not issue any commands while this work is going on”, but the RACF database is updated during normal work, for example with profile use counts, and last used date.

Plan B – REIPL with different data sets.

  • Convert to using IRRPRMxx PARMLIB member definitions to specify the data set names, instead of using a load module. See RACF setup, and changing the RACF dataset
  • Copy the RACF database to a recovery RACF data set using IRRUT200
  • Create a new IRRPRMxx member pointing to your recovery data set.
  • Create a new IEASYSxx member to use the RACF=xx member
  • You may have to create a new LOADxx member in SYS1.IPLPARM to point to the new IEASYSxx member.
  • REIPL, and specify the appropriate LOADxx suffix.
  • Fix the problem; copy from the recovery into the SYS1.RACFDS dataset and SYS1.RACFDS.BACKUP, so the primary and backup are the same.
  • Reipl using the normal IPL parameters

You could use the emergency stand-alone one pack system SARES1, but this may not have access to all of the data sets due to SMS and catalogs.