dls, dgrep, dzip: z/OS and Unix Unite!

Note: This blog was originally published in November 2017. It has been updated to include links to IBM’s software announced September 2019.

A little while back, I talked about mvscmd, which lets me run MVS programs from the z/OS USS environment (the UNIX shell).

I’ve written a few utilities that are now part of IBM Z Open Automation Utilities, which is provided as a free FMID in a few different IBM products including IBM Dependency Based Build, IBM Z Open Development, and IBM Developer for z/OS Enterprise Edition.

dls (dataset list)

dls takes a prefix as input and lists the datasets that start with that prefix. As an example, I have a bunch of test datasets that start with IBMUSER.MVSCMD. I can list them all to the console as follows:

 dls ibmuser.mvscmd

(the prefix is case-insensitive because datasets are upper-case only). Here is the output:

IBMUSER.MVSCMD.ADRDSU.DAR
IBMUSER.MVSCMD.BIND.OBJ
...
IBMUSER.MVSCMD.TSO.REXX

Here is a simplified version of dls:


if [ -z "$1" ]; then
 echo 'Syntax: dls <dataset-prefix>'
 echo 'Example: dls IBMUSER.MVSCMD'
 exit 16
else
 datasetprefix=$1;
 datasetprefix=$(echo ${datasetprefix} | tr '[:lower:]' '[:upper:]')
fi
(
 echo " LISTCAT -\n LEVEL(${datasetprefix}\n" | mvscmdauth --pgm=idcams --sysprint=* --sysin=stdin | awk '/0NONVSAM/ { print $3 }'
)

mls (PDS member list)

mls takes as input a PDS (or PDSE) and lists the members. I can list the members of the fully-qualified PDS IBMUSER.MVSCMD.C as follows:

mls ibmuser.mvscmd.c

Again, the dataset name is case-insensitive. Here’s the output:

  ERR
  MAIN

Here is a simplified version of mls:


if [ -z "$1" ]; then
 echo 'Syntax: mls <dataset>'
 echo 'Example: mls SYS1.PARMLIB'
 exit 16
else
 dataset=$1;
fi
tsocmd listds "'"${dataset}"'" members 2>/dev/null | tail +7

dgrep (Dataset simplistic ‘grep’)

dgrep takes as input a string and a pattern of datasets to search across. I can search for the string rexx across all datasets with the pattern IBMUSER.MVSCMD.TSO.* as follows:

dgrep rexx ibmuser.mvscmd.tso.*

Here’s the output:

 LINE-#  SOURCE SECTION     SRCH DSN: IBMUSER.MVSCMD.TSO.REXX
 OPERCMD          --------- STRING(S) FOUND -------------------
      1  /* REXX */

Here is a simplified version of dgrep:


if [ -z "$2" ]; then
 echo 'dgrep <str> <dataset-pattern>'
        echo '  example: dgrep rexx IBMUSER.MVSCMD.TSO.*'
        exit 16
else
 str=$1;
 datasetpattern=$2;
 datasetpattern=$(echo ${datasetpattern} | tr '[:lower:]' '[:upper:]')
fi
datasets=`echo " LISTCAT -\n ENTRIES("${datasetpattern}")\n" | mvscmdauth --pgm=idcams --sysprint=* --sysin=stdin | awk '/0NONVSAM/ { print $3 }' `
for dataset in ${datasets}; do
 echo "SRCHFOR '"${str}"'\n" | mvscmd --pgm=isrsupc --args='SRCHCMP,ANYC,IDPRFX,NOSUMS,LONGLN,NOPRTCC' --newdd=${dataset} --outdd=* --sysin=stdin | awk '!/  ISRSUPC/';
done

dzip: dataset zip

I have one more example, which took me awhile to get working, but could be really handy. It’s not part of the utilities, but I include it here as another example of the mvscmdauth utility. dzip takes a set of datasets as input and dumps them into a ‘blob’ using ADRDSSU. It then packs that ‘blob’ into an FB 1024 file that can be sent to other systems (or off-platform for backup).

I can backup all my datasets that start with IBMUSER.MVSCMD as follows:

dzip IBMUSER.MVSCMD.**

Here’s the (pruned) output:

- DUMP OUTDD(ARCHIVE) -
     DS(INCL(IBMUSER.MVSCMD.**)
 ADR101I (R/I)-RI01 (01), TASKID 001 HAS BEEN ASSIGNED TO COMMAND 'DUMP '
 ADR016I (001)-PRIME(01), RACF LOGGING OPTION IN EFFECT FOR THIS TASK
0ADR412E (001)-DTDSC(03), DATA SET IBMUSER.MVSCMD.LOAD IN CATALOG CATALOG.Z22C.MASTER ON VOLUME C2SYS1 FAILED SERIALIZATION
                          AND 0 FAILED FOR OTHER REASONS
0ADR454I (001)-DTDSC(01), THE FOLLOWING DATA SETS WERE SUCCESSFULLY PROCESSED
0                          IBMUSER.MVSCMD.ADRDSU.DAR
...
0                          IBMUSER.MVSCMD.TSO.REXX
                          TASK    001
 ** AMA572I STARTING TERSE ENCODE   SPACK        18:10:19  11/02/2017 ****                                                           
 ** AMA527I  INPUT  - DDNAME : SYSUT1   DSNAME: IBMUSER.DZIP.TEMP.D31917                                                             
 ** AMA528I  OUTPUT - DDNAME : SYSUT2   DSNAME: IBMUSER.DZIP.TEMP.D31917.TRS                                                         
 ** AMA583I  INPUT DATASET SIZE IN BYTES: 1110619 OUTPUT DATASET SIZE IN BYTES: 72704 COMPRESSION RATIO: 6%                          
 ** AMA573I TERSE COMPLETE ENCODE   SPACK        18:10:20  11/02/2017 ****                                                           
 ** AMA504I  RETURN CODE: 0                                                                                                          
Datasets of pattern: IBMUSER.MVSCMD.** zipped to: /tmp/d31917.dzp

My dataset zip file is written to /tmp/d31917.dzp (this cries out for options to control the output file name). Note that one of the files IBMUSER.MVSCMD.LOAD was not dumped because it is in use. I could use binary transfer to move this zip anywhere. I can unzip the dataset zip file on a different z/OS system using dunzip, with a different high-level qualifier IBMTEST, as follows:

dunzip /tmp/d31917.dzp IBMTEST

Here’s the (copious) output that I have pruned:

...
** AMA583I  INPUT DATASET SIZE IN BYTES: 72704 OUTPUT DATASET SIZE IN BYTES: 1110619 COMPRESSION RATIO: 6%                          
...
0ADR395I (001)-NEWDS(01), DATA SET IBMUSER.MVSCMD.ADRDSU.DAR ALLOCATED WITH NEWNAME IBMTEST.MVSCMD.ADRDSU.DAR, ON VOLUME(S): C2DBAR
...
0ADR454I (001)-TDLOG(01), THE FOLLOWING DATA SETS WERE SUCCESSFULLY PROCESSED
0                          IBMUSER.MVSCMD.ADRDSU.DAR
...
0ADR013I (001)-CLTSK(01), 2017.306 18:19:05 TASK COMPLETED WITH RETURN CODE 0000
0ADR012I (SCH)-DSSU (01), 2017.306 18:19:05 DFSMSDSS PROCESSING COMPLETE. HIGHEST RETURN CODE IS 0000

Please note: ADRSSU first extracts each dataset to the original source name, then renames the dataset to the target name. Therefore the ID that does the unzip has to have SAF authority for both the original dataset name and the target dataset name. In my example, I need to be able to create datasets starting with IBMUSER -and- IBMTEST. If someone knows how to eliminate this restriction through using ADRDSSU a different way, tell me.

dzip:

#
# simple program that 'zips' (archives) a set of datasets into a blob
#
if [ -z "$1" ]; then
 echo 'dzip <dataset-pattern>'
        echo '  example: dzip IBMUSER.MVSCMD.**'
        exit 16
else
 datasetpattern=$1;
fi
hlq=`./hlq`
rnd=${RANDOM}
tempds="${hlq}.DZIP.TEMP.D${rnd}"
temphfs=/tmp/d${rnd}.dzp
tso "alloc dsn('${tempds}') recfm(u) lrecl(0) dsorg(ps) dsntype(basic) catalog tracks space(1000,1000)" >/dev/null 2>&1
tso "alloc dsn('${tempds}.TRS') recfm(f,b) lrecl(1024) dsorg(ps) dsntype(basic) catalog tracks space(1000,1000)" >/dev/null 2>&1
(
 echo " DUMP OUTDD(ARCHIVE) -\n    DS(INCL(${datasetpattern}))" | 
    mvscmdauth --pgm=ADRDSSU --archive=${tempds},old --sysin=stdin --sysprint=stdout |
    awk '!/1PAGE|ADR109I|ADR006I|ADR801I|ADR006I|ADR013I|ADR012I/'
)
mvscmd --pgm=AMATERSE --args='SPACK' --sysut1=${tempds} --sysut2=${tempds}.TRS --sysprint=*
cp -B "//'"${tempds}.TRS"'" ${temphfs}
echo "Datasets of pattern: ${datasetpattern} zipped to: ${temphfs}"
tsocmd "delete '${tempds}'" >/dev/null 2>&1
tsocmd "delete '${tempds}.TRS'" >/dev/null 2>&1

dunzip:

#
# simple program that 'unzips' (restores) a blob into a set of datasets with an optional new HLQ
#
#set -x
if [ -z "$1" ]; then
 echo 'dunzip <src> [<HLQ>]'
 echo '  Unzip datasets from <src> archive, changing HLQ of datasets to <HLQ>'
        echo '  example: dunzip /tmp/d38382.dzp TEST'
        exit 16
else
 infile=$1;
 if [ -z "$2" ]; then
 newhlq=`./hlq`
 else
 newhlq=$2
 fi 
fi
hlq=`./hlq`
rnd=${RANDOM}
tempds="${hlq}.DZIP.TEMP.D${rnd}"
tso "alloc dsn('${tempds}') recfm(u) lrecl(0) dsorg(ps) blksize(27998) dsntype(basic) catalog tracks space(1000,1000)" >/dev/null 2>/dev/null
tso "alloc dsn('${tempds}.TRS') recfm(f,b) lrecl(1024) dsorg(ps) dsntype(basic) catalog tracks space(1000,1000)" >/dev/null 2>/dev/null
cp -Wseqparms='recfm=*' -B ${infile} "//'"${tempds}.TRS"'" 
mvscmd --pgm=AMATERSE --args='UNPACK' --sysut1=${tempds}.TRS --sysut2=${tempds} --sysprint=*
echo " RESTORE INDD(ARCHIVE) -\n    DS(INCL(**)) -\n    CATALOG -\n RENUNC(${newhlq})" | 
    mvscmdauth --pgm=ADRDSSU --archive=${tempds} --sysin=stdin --sysprint=stdout
tsocmd delete "'"${tempds}"'" >/dev/null 2>&1
tsocmd delete "'"${tempds}.TRS"'" >/dev/null 2>&1

A few of my scripts reference a tool called hlq.

Simplified version of hlq:

#
# print the hlq for this TSO user to the screen
#
tso profile 2>/dev/null | awk '/IKJ56688I/ { print $11; }' | /bin/sed -e "s/PREFIX(\([A-Z]*\))/\1/" 

Posted

in

,

by

Comments

3 responses to “dls, dgrep, dzip: z/OS and Unix Unite!”

  1. […] getting access to my tools that I use such as mvscmd, opercmd and dls that I have talked about in previous posts, which are under git source code management. So I need to install git on z/OS and configure it to […]

    Like

  2. […] Next, I discussed how core dataset services like dls and dgrep could be built using tsocmd and mvscmd to make them more Unix-like. […]

    Like

  3. JSSidman Avatar
    JSSidman

    I’d love to know how you managed to edit those long quoted command lines

    Like

Leave a comment