はじめに
常々、PCOMのインターフェースをどうにかしたいと思っておりました。z/OSの技術者が減っていく諸悪の根源の1つがこのPCOMのUIだと思っています。
とあるプロジェクトにアサインされた若者がPCOMを見て放った
「常軌を逸したインターフェースですね」
という一言が忘れられません。z/OS Explorerとかz/OSMFとかZoweとか、新しいインターフェースが提供され始めましたが、そこに移行するにはもう少し時間がかかりそうです。これらがセットアップとかメンテナンスとかリソース不足とかパフォーマンスをほとんど意識することなく普通にデフォルトで使えるようになるといいんですけど、まだちょっとハードルがあるように思います。(ZoweのCLIには期待していたのですが、普段のオペレーションで使うにはちょっとコレジャナイ感があったし...)
ということで、ここに新たなz/OSのオペレーション方法を提案します。
...と、大口叩いてみたものの、実体としてはUSS上にちょっとしたREXX, Shell Scriptの作り物をして、teratermでいくつかの操作ができるようにしてみた、というものです。
作成物はGitHubに公開しています。
PCOMを無くせるとは思っていませんが、できるだけ他のインターフェース(主にteraterm)を活用して作業効率を上げる、あるいは、Unixに慣れている人にとって使いやすいインターフェース(CUI)を提供する、しかもそれを軽量な仕組みで実現する(Lightweight)、というのが狙いです。
GitHub: Lightweight Command Utility on USS
参考:
z/OSのユーザー・インターフェースについて考える ~teraterm利用のすゝめ~
USSからREXX, シェル・スクリプトでz/OSを操作する
概要
PCOMでよく利用するオペレーションの一部をteratermから行えるようにします。SYSLOG, JOBLOG, システムコマンド実行、PDSメンバー操作、辺りのオペレーションが対象です。そのために、USS上で稼働するREXX, Shell Script群を提供しています。
z/OS側では、USSが使えるユーザーとsshデーモンの稼働が前提となります(ここがハードルになってしまう場合もありますが、さすがにここは避けて通れません)。
また、一部の機能(dsExplorer.shのldサブコマンド)では、内部的にFTPを使っているので、FTPサーバーも上がっていることが前提です。
ただ、z/OSMF, Java, Node.jsなどは一切使っていないので、古いz/OS環境でも利用できると思います。
基本的には、提供しているスクリプト群をUSS上の適当な場所に配置して、PATHとaliasを設定してあげればよいです(設定方法などは後述)。
他の追加コンポーネントは不要です。
セキュリティ設定について以下の辺りを参照のこと。
参考: REXXからSDSFアクセスについて
シェル上で各種テキスト情報を扱うようにしているため、Unixユーザーには馴染み深い方法で情報を扱えるのが特長です。例えば、grepで特定のキーワードを含む行だけ抽出したり、ファイルにリダイレクトしたり、必要な情報をコピペしたりするのが非常にやりやすくなると思います。
とりあえずどういうイメージで操作ができるかを手っ取り早く見たい場合は、先に下のユーティリティ使用例のデモ動画をご参照下さい。
ユーティリティ機能説明
当Utilityで提供している機能について説明します。
このユーティリティでは主に以下の操作をUSSシェルから(ssh経由で接続したteratermから)利用するため機能を提供しています。
- SYSLOG表示
- SDSFコマンド実行
- STパネル/DAパネル相当のJOB一覧参照、および、JOBLOG確認
- JCLサブミット
- MVSデータセット参照、PDSメンバー編集(vi)
※ちょこちょこアップデートは入れているので、細かいところは少しずつ変わる可能性がありますのでご了承下さい。
SYSLOG表示
関連ソース:
syslog.sh
syslog.rex
SYSLOGを参照するための機能です。
$ syslog.sh -h
Usage: syslog.sh [-h] | [-w [n] ] [-l [n] ] | [-fd YYYY/MM/DD] [-ft hh:mm:ss] [-td YYYY/MM/DD] [-tt hh:mm:ss]
-h: Show this help
-w [n]: Watch(tail) syslog with specifed interval in second. n=1-300 (default: 2sec)
-l [n]: Display syslog of last <n> minutes. n=1-59 (default: 1min)
-fd YYYY/MM/DD From Date (default: today)
-ft hh:mm:ss From Time (default: 00:00:00)
-td YYYY/MM/DD To Date (default: today)
-tt hh:mm:ss To Time (default: now)
without option Display syslog of last 1 minute.
直近のSYSLOG表示
何もオプションを指定しないと、直近1分間のSYSLOGを標準出力に表示します。
-lオプションで分単位で直近分のSYSLOGを表示できます(lはLastの頭文字)。
例:
syslog.sh
: 直近1分のSYSLOGを出力
syslog.sh -l 10
: 直近10分のSYSLOGを出力
特定の期間のSYSLOG表示
-fd, -ft, -td, -tt オプションで、表示させたい期間を指定して、その期間のSYSLOGを表示できます。
(オプション名は、それぞれFromDate, FromTime, ToDate, ToTimeの略です)
4つのうちいずれかのオプションを指定した場合、特定期間のSYSLOG表示となります。
Fromのデフォルトは当日の00:00:00、Toのデフォルトはスクリプト実行タイミングです。
例:
syslog.sh -ft 10:00:00
: 当日の10:00から現在時刻までのSYSLOGを出力
syslog.sh -tt 01:00:00
: 当日の00:00~01:00までのSYSLOGを出力
syslog.sh -ft 10:00:00 -tt 11:00:00
: 当日の10:00~11:00までのSYSLOGを出力
syslog.sh -fd 2019/05/01 -ft 23:00:00 -td 2019/05/02 -tt 01:00:00
: 2019/05/01 23:00:00 ~ 2019/05/02 01:00:00 までのSYSLOGを出力
最新のSYSLOGを自動更新
-wオプションを指定すると、ファイルをtailしているようなイメージで、SYSLOGメッセージが追加されたら自動で表示させることができます(wというのはWatchの頭文字)。作業中はそのウィンドウ(シェル)はSYSLOG表示専用として置いておくのがよいでしょう。
デフォルトでは2秒おきに最新部分をAppendしていくことになりますが、更新間隔を秒単位で指定することも可能です。
-lオプションとの併用する場合、直近n分のSYSLOGを表示した上で、自動更新モードに入ります。
例:
syslog.sh -w
: 直近1分のSYSLOG表示後、2秒間隔で自動更新を繰り返す
syslog.sh -l 5 -w 10
: 直近5分のSYSLOG表示後、10秒間隔で自動更新を繰り返す
注意!
SYSLOGを取得するのに、REXXからAddress SDSF "ISFLOG READ TYPE(SYSLOG)"
というコマンドを使っており、この時、ISFLOGSTARTTIME, ISFLOGSTARTDATE, ISFLOGSTOPTIME, ISFLOGSTOPDAT という変数で取得する時刻を指定しています。ところが、マニュアルをよくよく見てみると、以下のような記述がありました。
Browsing the system log with ISFLOG
ISFLOGSTARTTIME, ISFLOGSTARTDATE, ISFLOGSTOPTIME and ISFLOGSTOPDATE define the date and time range for the records. Use them to ensure that your date and time range is reasonable, so that an excessive number of variables is not created.
When these special variables are used, SDSF positions the SYSLOG as near as possible to the requested record. However, due to the precision used for time stamps and the time the record is actually written to SYSLOG, it is possible that this may be several lines away from the desired record.
記録されているタイムスタンプと実際に書かれるタイミングが若干ずれる可能性があるらしい。まぁそれはよいとしても、上の変数で指定した時刻と、実際返されるSYSLOGデータにズレがあるっぽい!実際、時刻を一定時間ずらして取得する今回のスクリプトでは、一部メッセージがロストしてしまうケースがありました。うむむ、イケてない。厳密にSYSLOG取得しなければいけないケースだとちょっと向かないです...。うぐぐ。
SDSFシステムコマンド実行
関連ソース:
sdsf.rex
システムコマンドを実行するための機能です。
usage:
sdsf.rex <command>
これだけ。
コマンドの結果として返されるものは、標準出力に表示します。
# sdsf.rex d iplinfo
RC: 0
ISFMSG: COMMAND ISSUED
ISFMSG2.1 : ISF776I Processing started for action 1 of 1.
ISFMSG2.2 : ISF769I System command issued, command text: d iplinfo.
ISFMSG2.3 : ISF766I Request completed, status: COMMAND ISSUED.
ZOS1 2019136 20:49:05.64 ISF031I CONSOLE CICS004 ACTIVATED
ZOS1 2019136 20:49:05.64 -d iplinfo
ZOS1 2019136 20:49:05.65 IEE254I 20.49.05 IPLINFO DISPLAY 459
SYSTEM IPLED AT 10.51.54 ON 04/01/2019
RELEASE z/OS 02.03.00 LICENSE = z/OS
USED LOADA0 IN SYS0.IPLPARM ON 08889
ARCHLVL = 2 MTLSHARE = N
IEASYM LIST = 08
IEASYS LIST = (A0) (OP)
IODF DEVICE: ORIGINAL(08889) CURRENT(08889)
IPL DEVICE: ORIGINAL(08882) CURRENT(08882) VOLUME(EP23T1)
JOBLOG表示
関連ソース:
joblog.sh
jobddlist.rex
joblog.rex
joblog_dd.rex
joblog_purge.rex
JOBLOGを参照するための機能です。
JOBIDを引数にして、起動すると専用プロンプトが表示され、対話形式でJOBLOGに対する操作ができます。
$ joblog.sh
Usage:
$ /u/cics004/Util/joblog.sh <JOBID>
Example1:
$ /u/cics004/Util/joblog.sh STC03076
※この機能は単発で使うこともできますが、後続のスクリプトと合わせ技で使う想定の機能です。
起動すると、当該JOBに対して、DDのリストが表示され、DD毎にJOBLOGを操作できます。
$ joblog.sh STC00733
-----------------------
JOBNAME: CT54D4A1
JOBID: STC00733
OWNER: IBMUSER
Max-RC:
-----------------------
No. DDNAME StepName ProcStep DSID Owner Rec-Cnt Byte-cnt CrDate-CrTime
========================================================================================
1 JESMSGLG JES2 - 2 IBMUSER 2 136 2019.176 14:16:34
2 JESJCL JES2 - 3 IBMUSER 120 10976 2019.176 14:16:34
3 JESYSMSG JES2 - 4 IBMUSER 2 143 2019.176 14:16:34
4 DFHCXRF CT54D4A1 - 101 IBMUSER 0 - 2019.176 14:16:35
5 MSGUSR CT54D4A1 - 103 IBMUSER 854 86036 2019.176 14:16:35
6 CEEMSG CT54D4A1 - 104 IBMUSER 0 - 2019.176 14:16:35
7 CEEOUT CT54D4A1 - 105 IBMUSER 0 - 2019.176 14:16:35
8 COUT CT54D4A1 - 109 IBMUSER 0 - 2019.176 14:16:36
9 CRPO CT54D4A1 - 110 IBMUSER 0 - 2019.176 14:16:36
-------------------------
Select 0 for All DDs or DD Number (with file name optionally), or Input quit
subcommand usage
0 :Display Whole JOBLOG
<num> :Display JOBLOG of selected DD
<num> <file> :Output selected JOBLOG to file
r :Refresh DD list
q|quit :Quit this shell script
CT54D4A1/STC00733 >>>
上の例は、稼働中のCICSのJOBIDを指定して、当機能を実行した例です。
DDのリストと、サブコマンドの使い方が表示されます。
最終行に専用のプロンプトCT54D4A1/STC00733 >>>
が表示されます(行頭の文字列は、参照しているJOBNAME/JOBIDを表しています)。
このプロンプトに、DD名の左に表示されている番号を入力すると、そのDDの内容が表示されます。結果は"more"コマンドで表示されるので、moreのサブコマンドで表示を制御することができます([space]で次ページ、[b]で前ページ、[/]でキーワード検索、など)。
0番を入力すると、DD毎ではなくJOBLOG全体が表示されます。
番号の後にブランク区切りで文字列(joblog.txt)などを入力すると、結果がファイルにリダイレクトされます。
サブコマンド未入力でカラEnterを押すと、再度DDリストが表示されます。
rでDDリストのリフレッシュが行われ、qでこのプロンプトを抜けます。
なお、このJOBLOGのDDのリストは、シェルスクリプト実行中は一時ファイル(テキストファイル)に情報を保持し、最後に削除するようにしています。一時ファイルは、/tmp/Util_<pid>_<YYYYMMDD>_<hhmmss>.txt
というfile名で保持します。シェルスクリプトを途中で異常終了させたりするとゴミが残る可能性がありますのでご注意ください。
STパネル情報表示
関連ソース:
st.sh
st.rex
(+JOBLOG表示用スクリプト)
STパネルの情報を参照するための機能です。
$ st.sh -h
Usage: st.sh [-j jobname] [-o owner] [-i]
-j: jobname filter (pertial match)
-o: owner filter (partial mathc)
-i: interactive mode
$ st.sh -o cics004
No. JOBNAME JobID Owner Prty Queue PhaseName C Pos Max-RC Status SysName
================================================================================================================
1 CICS004 TSU08034 CICS004 15 EXECUTION EXECUTING - - - - ZOS1
2 LISTC JOB07460 CICS004 1 PRINT AWAITING OUTPUT A 1260 CC 0000 - -
3 TAGBPX01 JOB07461 CICS004 1 PRINT AWAITING OUTPUT A 1261 CC 0000 - -
4 LISTC JOB07464 CICS004 1 PRINT AWAITING OUTPUT A 1262 CC 0000 - -
5 TAGBPX01 JOB07508 CICS004 1 PRINT AWAITING OUTPUT A 1284 CC 0000 - -
6 TAGBPX01 JOB07511 CICS004 1 PRINT AWAITING OUTPUT A 1286 CC 0000 - -
7 TAGBPX01 JOB07512 CICS004 1 PRINT AWAITING OUTPUT A 1287 CC 0000 - -
8 TAGBPX01 JOB07513 CICS004 1 PRINT AWAITING OUTPUT A 1288 CC 0000 - -
9 LISTC JOB07515 CICS004 1 PRINT AWAITING OUTPUT A 1289 CC 0000 - -
10 LISTC JOB07539 CICS004 1 PRINT AWAITING OUTPUT A 1300 CC 0000 - -
11 LISTC JOB07565 CICS004 1 PRINT AWAITING OUTPUT A 1307 CC 0000 - -
12 TRANCBL JOB08060 CICS004 1 PRINT AWAITING OUTPUT A 1606 CC 0008 - -
13 TRANCBL JOB08066 CICS004 1 PRINT AWAITING OUTPUT A 1610 CC 0000 - -
JOBリスト表示のみ
引数を何も指定せずにst.shを実行すると、STパネルで表示できる全JOBのリストが表示されます。
-jオプション、-oオプションで、それぞれJOBNAME, OWNERでの絞込みができます(両方指定した場合はAND条件となります)。
それぞれのオプションで指定する文字列は部分一致でのフィルターになります。
指定した文字列は大文字に変換して検索するので、小文字での指定でもOKです。
例:
st.sh
: STパネルに表示される全JOBのリストを表示
st.sh -j ct54
: JOBNAMEに"CT54"を含むJOBのリストを表示
st.sh -j tran -o cics004
: JOBNAMEに"TRAN"を含み、かつ、OWNERに"CICS004"を含むJOBのリストを表示
対話モード
さらに、-iオプションを指定すると、リスト表示に続いて専用プロンプトが表示され、対話形式でリストされたJOBを操作することができます。
$ st.sh -j ct54 -i
No. JOBNAME JobID Owner Prty Queue PhaseName C Pos Max-RC Status SysName
================================================================================================================
1 CT54D0CM STC00597 IBMUSER 15 EXECUTION EXECUTING - - - ARMELEM ZOS1
2 CT54D0WE STC03070 IBMUSER 15 EXECUTION EXECUTING - - - ARMELEM ZOS1
3 CT54D4A1 STC03076 IBMUSER 15 EXECUTION EXECUTING - - - ARMELEM ZOS1
4 CT54DMA1 STC08021 IBMUSER 15 EXECUTION EXECUTING - - - ARMELEM ZOS1
-------------------------
Select JOBID Number, or Input quit
subcommand usage
<num> :Display DD list
<num> p :Purge JOBLOG
r :Refresh JOBID list
q|quit :Quit this shell script
ST: >>
末尾に専用のプロンプトST: >>
が表示されます。
ここに、JOBのリストの左の数字を入力すると、当該JOBのJOBIDを指定して先のJOBLOG表示機能が呼び出されます。つまり、ここからJOBを選択してそのJOBLOGを見ることができます。
数字の後にpを入力すると、選択したJOBをPurgeすることができます。
サブコマンド未入力でカラEnterを押すと、再度JOBのリストが表示されます。
rでJOBリストのリフレッシュが行われ、qでこのプロンプトを抜けます。
DAパネル情報表示
関連ソース:
da.sh
da.rex
(+JOBLOG表示用スクリプト)
DAパネルの情報を参照するための機能です。
使い方はSTと同様なので割愛します。
JCLサブミット
関連ソース:
submitJcl.sh
checkJobStatus.rex
(+JOBLOG表示用スクリプト)
JCLをサブミットする機能です。
$ submitJcl.sh -h
Usage: submitJcl.sh [-f <jcl_file> | -d <jcl_dataset>] [-i|-s] [-t <timeout>] [-p <propertyFile> | -l <propertyList>]
-f : specify uss file
-d : specify PDS member
-i : interactive mode to display JOBLOG
-s : script mode to execute in shell script
-t : timeout in sec for waiting JOB completion
default 0 sec (no timeout) / speciry between 0 to 3600
-p : specify property file name on USS
(@prop01@=XXX in property file means replacement from @prop01@ to XXX in JCL)
-l : specify property list instead of file in following format: @prop01@=XXX,@bbb@=YYY,@ccc@=ZZZ
-c : check JCL before submit
Example1: submitJcl.sh -f sleep.jcl
Example2: submitJcl.sh -d 'CICSSHR.CICS004.JCLLIB(LISTC)'
Example3: submitJcl.sh -f template.jcl -l "@prop01@=XXX,@prop02@=YYY"
実行したいJCLとしては、-fオプションでUSS上のファイルか、-dオプションでPDSメンバーのいずれかを指定できます。
-fオプションで指定するファイルは、相対パスもしくは絶対パスで指定します。
-dオプションで指定するPDSメンバーは、シングルクォーテーションでくくります。
サブミットのみ
例:
submitJcl.sh -f sleep.jcl
: カレントディレクトリにあるsleep.jclをサブミット
submitJcl.sh -f /u/cics004/test/sleep.jcl
: /u/cics004/test/sleep.jclをサブミット
submitJcl.sh -d 'CICSSHR.CICS004.JCLLIB(LISTC)'
: PDSメンバー'CICSSHR.CICS004.JCLLIB(LISTC)'をサブミット
いずれも、JobID: JOB08350
というように、JobIDが結果として返されます。
対話モード
-iオプションを指定してJCLをサブミットした場合、当該JOBの完了を待って、Max-RCを表示、さらに、JOBLOG表示機能が呼び出され、JOBLOGを確認することができます。
$ submitJcl.sh -f sleep.jcl -i
JobID: JOB08352
waiting......
Max-RC: CC 0000
-----------------------
JOBNAME: TAGBPX01
JOBID: JOB08352
OWNER: CICS004
Max-RC: CC 0000
-----------------------
No. DDNAME StepName DSID Owner Rec-Cnt Byte-cnt CrDate-CrTime
==============================================================================
1 JESMSGLG JES2 2 CICS004 20 1185 2019.136 22:20:43
2 JESJCL JES2 3 CICS004 9 519 2019.136 22:20:43
3 JESYSMSG JES2 4 CICS004 20 1157 2019.136 22:20:43
4 STDOUT STEP1 103 CICS004 4 105 2019.136 22:20:43
-------------------------
Select 0 for All DDs or DD Number (with file name optionally), or Input quit
subcommand usage
0 :Display Whole JOBLOG
<num> :Display JOBLOG of selected DD
<num> <file> :Output selected JOBLOG to file
r :Refresh DD list
q|quit :Quit this shell script
TAGBPX01/JOB08352 >>>
上の例は、意図的にSleepを入れて少し時間のかかるJOBを実行した例です。
JobIDを出力した後に、waiting....
という表示がありますが、ここがJOBの完了を待っていることを表しています。1秒間隔でJOBのステータスをチェックしにいきその都度「.」を出力しています(時間がかかるJOBはwaitingの後の「.」が長くなっていく)。
JOBが完了すると、Mac-RCを出力し、JOBLOG表示機能が自動的に呼ばれ、JOBLOGを確認することができます。
デフォルトではJobの完了を待つタイムアウト値は0sec(タイムアウトなし)ですが、-tオプションで明示指定することもできます(秒単位)。
スクリプトモード
-sオプションを指定してJCLをサブミットした場合は、スクリプトモードとなります。
このモードは、自動化などのためにスクリプトから実行されることを想定しています。
当該JOBの完了を待って、Max-RCを表示します。
JOBのRCが0~255以内であれば、それをシェルの実行結果コードとして返します。
(exit の値としてRCを返すので、後続処理では$?で結果コードを判定可能)
それ以外(RCが255以上や、JCL ERROR, ABENDなど)の場合は結果コード255を返します。
-tオプションでタイムアウトを指定して、その時間内にジョブの実行が完了しなかった場合は結果コード200を返します。
テンプレートの使用
JCL中の一部の文字列を変数として埋め込んだテンプレートを用意しておき、実行時にその文字列を適切な文字列に置き換えて実行するためのオプション"-p", "-l"を用意しています。
変数は、他で使っていないような文字列として定義します。("@"を前後ではさんだ文字列など)
例えば、以下のようなJCLテンプレートを用意します。
//@JOBNAME@ JOB ,CLASS=A,MSGCLASS=X
//*********************************************************************
//STEP1 EXEC PGM=BPXBATCH,REGION=0M,MEMLIMIT=4G,
// PARM='PGM /u/cics004/Util_test/sleep.sh 10'
//STDOUT DD SYSOUT=*
//STDERR DD SYSOUT=*
//STDENV DD *
ENVTEST1=aaa
ENVTEST2=bbb
PTEST01=@prop_Test01@
PTEST02=@prop_Test02@
PTEST03=@prop_Test03@
PTEST04=@prop_Test04@_@prop_Test01@_@prop_Test04@
PTEST05=@prop_Test05@
/*
//
上のJCLでは、@JOBNAME@
や、@prop_Test01@
が変数として定義されています。
これらの変数に具体的な値を設定するためのプロパティファイルを用意します。
@JOBNAME@=TAGSLEEP
@prop_Test01@=AAA
@prop_Test02@=BBB
@prop_Test03@=CCC
@prop_Test04@=DDD
@prop_Test05@=EEE
これを使って、以下のようにJCLをサブミットすると、test_properties.txtの内容でJCLテンプレートの変数が置き換えられて実行されます。
$ submitJcl.sh -i -f test_template.jcl -p test_properties.txt
変数名が少ない場合は、プロパティファイルを作らなくても、以下のようなフォーマットで-lオプションで直接変数名と値を指定できます。
$ submitJcl.sh -i -f test_template.jcl -l "@JOBNAME@=TAGSLEEP,@prop_Test01@=AAA,@prop_Test02@=BBB,@prop_Test03@=CCC,@prop_Test04@=DDD,@prop_Test05@=EEE"
-c
オプションを使用すると、変数置換後のJCLを事前にチェックしてからJCLを実行することができます。
(moreでJCLを確認し、その後プロンプトでy/nを選択することでJCLの実行/キャンセルが可能)
※注意点
この仕組みでは、JCLテンプレートとして指定されたテキストファイル中の、xxx=yyy
という式の左辺の文字列を単純に右辺の文字列に置換しているだけですので、JCL中の任意の箇所を変数に置き換えることができます。ただし、指定された後の文字列によって桁数のずれが生じる可能性がありますので、テンプレートの作成、値の指定は、桁数を意識した上で実施する必要があります。
また、変数の置換には内部的にsedコマンドを使用しています。そのため、置換前後の文字列に「/
」や「(
」など一部の記号についてはバックスラッシュによるエスケープ表記をする必要があります。
例:「\/
」,「\(
」
MVSデータセット操作
関連ソース:
dsExplorer.sh
MVSデータセット(主にPDSのメンバー)を、USS上のファイルっぽく操作できるようにしたものです。
専用プロンプトが表示され、対話モードで実行することになります。
$dsExplorer.sh
-------------------------
subcommand usage
pwd :Print current working directory
cd <dir> :Change working directory
you can specify absolute/relative path with using ".."
ls :List dataset for current working directory
lm :List member for current working directory (valid only at PDS dataset)
ld :List detail of dataset for current working directory by using ftp
this command requires ftp password at first time
vi <member> :Edit/Create member in current working directory by using vi
rm <member> :Remove member in current working directory
cp <mem1> <mem2> :Copy member from <mem1> to <mem2> in current working directory
clear :Clear cached ftp password
q|quit :Quit this shell script
/ >>>
サブコマンド: cd
ドット(.)区切りのデータセットをディレクトリのように見立てて、cd (Change Directory)コマンドで移動できます。CICSSHR.CICS004.JCLLIBという構造のデータセットがあった場合、cd /cicsshr/cics004/jcllib といった感じで移動できます。
絶対パス、相対パス指定ができ、一つ上の上位ディレクトリは「..」で指定できます。
/ >>> cd /cicsshr/cics004/jcllib
/cicsshr/cics004/jcllib >>>
プロンプトの先頭に現在の作業ディレクトリが表示されます。
最初はルートディレクトリです。
サブコマンド: pwd
ドット(.)区切りのデータセットをディレクトリのように見立てて現在の作業ディレクトリを表示します。
表示はデータセット形式で、大文字/ドット区切りです。
/cicsshr/cics004/jcllib >>> pwd
CICSSHR.CICS004.JCLLIB
サブコマンド: ls
現在の作業ディレクトリ下のデータセットのリストを表示します。
ルートディレクトリにいる場合はHLQのリスト、それ以外の場合はデータセットのリストが表示されます。
パイプが1度だけ使えますので、grepやmoreと組み合わせて利用できます。
/ >>> ls | grep SYS
SYS0
SYSADMIN
SYSGEN21
SYSLOGD
SYS1
/ >>> cd SYS0
/SYS0/ >>> ls | more
0 NONVSAM SYS0.ARM.CDS01
1 NONVSAM SYS0.ARM.CDS02
2 NONVSAM SYS0.CFRM.CDS01
3 NONVSAM SYS0.CFRM.CDS02
4 NONVSAM SYS0.CMDPROC
5 CLUSTER SYS0.IODF00.CLUSTER
6 DATA SYS0.IODF00
7 NONVSAM SYS0.IODF00.WORK.ACTLOG
8 CLUSTER SYS0.IODF00.WORK.CLUSTER
9 DATA SYS0.IODF00.WORK
10 NONVSAM SYS0.IODF01.ACTLOG
11 CLUSTER SYS0.IODF01.CLUSTER
12 DATA SYS0.IODF01
13 NONVSAM SYS0.IPLPARM
14 NONVSAM SYS0.ISPPLIB
15 NONVSAM SYS0.LINKLIB
16 NONVSAM SYS0.LOGR.CDS01
17 NONVSAM SYS0.LOGR.CDS02
18 NONVSAM SYS0.OMVS.CDS01
19 NONVSAM SYS0.OMVS.CDS02
20 NONVSAM SYS0.PARMLIB
21 NONVSAM SYS0.PARMLIB.BK180806
22 NONVSAM SYS0.PARMLI2
23 NONVSAM SYS0.PROCLIB
24 NONVSAM SYS0.PROCLIB.BACKUP
25 NONVSAM SYS0.SFM.CDS01
26 NONVSAM SYS0.SFM.CDS02
27 NONVSAM SYS0.TCPPARMS
28 NONVSAM SYS0.VTAMLIB
29 NONVSAM SYS0.VTAMLST
30 NONVSAM SYS0.WLM.CDS01
31 NONVSAM SYS0.WLM.CDS02
32 NONVSAM SYS0.XCF.CDS01
33 NONVSAM SYS0.XCF.CDS02
34 NONVSAM SYS0.Z21VUP.CATALOG.Z23
35 NONVSAM SYS0.Z21VUP.JCLLIB
36 NONVSAM SYS0.Z23VUP.JCLLIB
37 NONVSAM SYS0.Z23VUP.PREWORK.JCLLIB
38 ALIAS SYS0
--More--(EOF)
サブコマンド: lm
現在の作業ディレクトリがPDS/PDSEの場合に、そこに含まれるメンバーのリストを表示します。
/ >>> cd /cicsshr/cics004/jcllib
/cicsshr/cics004/jcllib >>> lm
--VOLUMES--
Z9CI01
--MEMBERS--
BAQJS2LS
BAQLS2JS
CBCMLK00
CPALIST
CPALISTE
CPASTAE
CPASUME
CPASUM1
CSDUPDEF
CSDUPLIS
(以下略)
サブコマンド: ld / clear
現在の作業ディレクトリ下のデータセットの詳細情報を表示します。
現在の作業ディレクトリがPDS/PDSEの場合には、そこに含まれるメンバーの詳細情報を表示します。
※注意
ルートディレクトリの場合は無効です。
この機能のみ、FTPを利用しています(自分自身のホスト名に対して、ログインしているユーザーを使ってFTP接続して情報を取得します)。
そのため、ldコマンド実行時は、最初のみパスワードの入力が求められます。パスワードはキャッシュされるので、2回目以降はパスワード入力の必要はありません。パスワードを間違うと情報の取得ができないので、いったんclearサブコマンドでキャッシュをクリアしてから再度パスワード入力して下さい。
/ >>> cd cicsshr/cics004
/cicsshr/cics004/ >>> ld
Input Password for CICS004 : xxxxxxxx
Volume Unit Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname
Z11CU1 3390 2018/02/08 1 5 VB 84 27998 PS CERTIP
Z11CU1 3390 2016/01/19 1 5 VB 84 27998 PS CERTWEB
Z11CU1 3390 2018/02/27 1 5 VB 84 27998 PS CERT2048
Z11SM1 3390 2016/01/19 1 5 VB 84 27998 PS CLICERT
Z9CI01 3390 2019/03/07 1 75 FB 80 27920 PO COPYLIB
ZR21W2 3390 2014/01/27 1 5 VB 84 27998 PS ISE2WEB
Z11CU1 3390 2014/01/27 1 5 VB 84 27998 PS ISE22048
Z11SM1 3390 2018/02/27 1 5 VB 84 27998 PS ISE3CTG
Z11CU1 3390 2014/02/03 1 5 VB 84 27998 PS ISE32048
Z9CI01 3390 2019/07/01 1 150 FB 80 27920 PO JCLLIB
Z9CI01 3390 2019/07/01 1 15 FB 80 27920 PO JCLLIB.BK
CICVLJ 3390 2019/05/28 2 1545 FB 140 14000 PO JOBLOG
Z9CI01 3390 2019/06/13 2 150 FB 80 27920 PO PGMSOR
Z9CI01 3390 2019/07/01 1 15 FB 80 27920 PO REXX
Z9CI01 3390 2019/06/25 1 150 U 23200 23200 PO USERLIB
Z9CI01 3390 2019/06/25 1 15 U 23200 23200 PO USERLIB2
250 List completed successfully.
/cicsshr/cics004/ >>> cd jcllib
/cicsshr/cics004/jcllib/ >>> ld
Name VV.MM Created Changed Size Init Mod Id
BAQJS2LS 01.01 2016/03/14 2016/10/25 18:54 100 100 0 CICS004
BAQLS2JS 01.07 2016/03/14 2016/10/25 18:54 101 101 0 CICS004
CBCMLK00 01.00 2012/10/17 2012/10/17 16:26 43 43 0 CICS004
CPALIST 01.24 2012/05/10 2016/06/09 16:55 90 75 0 CICS004
CPALISTE 01.27 2012/05/10 2016/06/13 20:17 93 75 0 CICS004
CPASTAE 01.26 2012/05/10 2016/06/13 20:27 65 78 0 CICS004
CPASUME 01.24 2012/05/10 2016/06/13 20:17 88 78 0 CICS004
CPASUM1 01.20 2012/05/10 2016/06/13 14:36 85 78 0 CICS004
CSDUPDEF 01.01 2016/01/18 2016/01/18 13:52 143 143 0 CICS004
CSDUPLIS 01.02 2016/01/18 2016/01/18 13:57 34 143 0 CICS004
(以下略)
※操作しようとしているメンバーの作成日や最終更新日時を確認したいということは多々あるので、この機能必要だよなと思ったのですが、USSからデータセットの詳細情報取ってくるうまい仕組みが見つかりませんでした。わざわざFTP使うのもどうかと思うのですがこれが一番手っ取り早く情報取れました(アイデアくれたKさんに感謝)。
ただ、頑張って無理やりFTPまで使ってこの機能を作ったのですが、後述のviサブコマンドを使ってファイル編集しちゃうと、内部的にはUSSファイルへコピー => 編集 => PDSメンバーへ上書きコピー という処理が行われることになり、そうすると作成日とか更新日時がブランクになってしまうという、なんとも残念な状況になってしまいました...。うむぅ。
サブコマンド: cp
現在の作業ディレクトリがPDS/PDSEの場合に、そこに含まれるメンバーをコピーします。(現行作業ディレクトリ内でのコピーのみ)
/cicsshr/cics004/jcllib/ >>> lm | grep LIST
CPALIST
CPALISTE
LISTC
LISTC2
LOGLIST
/cicsshr/cics004/jcllib/ >>> cp LISTC2 LISTC3
copy from CICSSHR.CICS004.JCLLIB(LISTC2) to CICSSHR.CICS004.JCLLIB(LISTC3)
/cicsshr/cics004/jcllib/ >>> lm | grep LIST
CPALIST
CPALISTE
LISTC
LISTC2
LISTC3
LOGLIST
サブコマンド: vi
現在の作業ディレクトリがPDS/PDSEの場合に、そこに含まれるメンバーをviで編集します。
裏では、一旦USS上のテンポラリーファイルに指定したメンバーの内容をコピーし、それをviエディターで開きます。保存すると、それをPDSメンバーとして上書きコピーします。
存在しないメンバー名を指定した場合は、新規にメンバーが作成されることになります。
/cicsshr/cics004/jcllib/ >>> vi LISTC3
//LISTC JOB MSGCLASS=X,CLASS=A,NOTIFY=&SYSUID 00012038
//*--test ------------------------------------------
//* 00014038
//GO EXEC PGM=IDCAMS,REGION=0M 00018038
//SYSPRINT DD SYSOUT=* 00019038
//SYSIN DD * 00020038
LISTC LEVEL('CICSTS54.@DBDC') 00021039
/* 00022038
~
~
~
~
~
~
"/tmp/Util_83952228_20190701_194149_LISTC3.txt" 8 lines, 620 characters
Override member? / CICSSHR.CICS004.JCLLIB(LISTC3)
(y/n) >>>y
save this change
Created new member CICSSHR.CICS004.JCLLIB(LISTC3)
サブコマンド: rm
現在の作業ディレクトリがPDS/PDSEの場合に、そこに含まれるメンバーを削除します。
/cicsshr/cics004/jcllib/ >>> lm | grep LIST
CPALIST
CPALISTE
LISTC
LISTC2
LISTC3
LOGLIST
/cicsshr/cics004/jcllib/ >>> rm LISTC3
Remove member? / CICSSHR.CICS004.JCLLIB(LISTC3)
(y/n) >>>y
remove this member
/cicsshr/cics004/jcllib/ >>> lm | grep LIST
CPALIST
CPALISTE
LISTC
LISTC2
LOGLIST
(参考)共通関数
ソース:
commonFunctions.sh
いくつかのシェル・スクリプトで使用するロジック(オプションのチェックなど)を共通関数として定義しています。
ユーティリティー使用例
さてさて、このユーティリティーを使うとどんな感じで作業ができるのか、実際の使用例をキャプチャしてみました。
シナリオ
この動画では、以下のような操作を行っています。
- SYSLOG表示(tail)
- CICSリージョンの稼働確認
- Displayコマンド
- DAパネル
- CICSリージョン停止
- Modifyコマンド(CEMT P SHUT)
- 起動プロシージャー編集
- viエディター
- CICSリージョン再起動
- Startコマンド
- CICS-COBOLプログラム編集
- viエディター
- コンパイル/リンク
- JCLサブミット
- CICS資源定義追加
- JCLサブミット
- CICS資源定義インストール
- Modifyコマンド(CEDA)
- テスト実施
- PCOMからCICS端末に接続してCECI(インタープリター)
- CICS JOBLOG確認
- DAパネル
このシナリオでは、アプリのテスト用にCICS端末接続するためにPCOM使っていますが、それ以外は全てteratermからオペレーションを行っています。(TSOは未使用)
前提
添付のデモ動画の環境では、操作しやすくするために、以下のようなAliasを設定したシェルにて実行しています。
UtilDir=/u/cics004/Util
export PATH=$UtilDir:$PATH
alias sdsf=sdsf.rex
alias d="sdsf d"
alias f="sdsf f"
alias s="sdsf s"
alias p="sdsf p"
alias v="sdsf v"
alias da="da.sh -i"
alias st="st.sh -i"
alias syslog=syslog.sh
alias jl="joblog.sh"
alias sub="submitJcl.sh -i"
alias ds="dsExplorer.sh"
UtilDirは、このUtilityのシェルスクリプト群を配置したディレクトリです。
DA情報確認とか、JCLサブミットは、デフォルトで対話モードにしたいので、-iオプション付きでalias定義しています。
上のスクリプトを、利用ユーザーの.profileに仕込んでおけばOKです。
. /u/cics004/Util/util_env.sh
デモ動画
— tomotagwork (@tomotagwork) July 15, 2019
補足
TSOコマンド実行
USSのシェルからTSOコマンドを実行するための機能はデフォルトで提供されています。その名も「tsocmd」。
Utilityとして提供しているシェル・スクリプト中からも使用しています。
[CICS004@EPLEX1:/u/cics004] tsocmd listuser
listuser
USER=CICS004 NAME=CICS004 OWNER=IBMUSER CREATED=02.129
DEFAULT-GROUP=ESA PASSDATE=19.175 PASS-INTERVAL= 30 PHRASEDATE=N/A
ATTRIBUTES=SPECIAL OPERATIONS
REVOKE DATE=NONE RESUME DATE=NONE
LAST-ACCESS=19.190/13:11:56
CLASS AUTHORIZATIONS=NONE
NO-INSTALLATION-DATA
NO-MODEL-NAME
LOGON ALLOWED (DAYS) (TIME)
---------------------------------------------
ANYDAY ANYTIME
GROUP=ESA AUTH=USE CONNECT-OWNER=IBMUSER CONNECT-DATE=02.129
CONNECTS= 2,665 UACC=NONE LAST-CONNECT=19.190/13:11:56
CONNECT ATTRIBUTES=NONE
REVOKE DATE=NONE RESUME DATE=NONE
SECURITY-LEVEL=NONE SPECIFIED
CATEGORY-AUTHORIZATION
NONE SPECIFIED
SECURITY-LABEL=NONE SPECIFIED
[CICS004@EPLEX1:/u/cics004] tsocmd "LISTCAT LEVEL('CICSSHR.CICS004')"
LISTCAT LEVEL('CICSSHR.CICS004')
NONVSAM ------- CICSSHR.CICS004.CERTIP
IN-CAT --- UCAT.Z9CI01
NONVSAM ------- CICSSHR.CICS004.CERTWEB
IN-CAT --- UCAT.Z9CI01
NONVSAM ------- CICSSHR.CICS004.CERT2048
IN-CAT --- UCAT.Z9CI01
NONVSAM ------- CICSSHR.CICS004.CLICERT
IN-CAT --- UCAT.Z9CI01
NONVSAM ------- CICSSHR.CICS004.COPYLIB
IN-CAT --- UCAT.Z9CI01
NONVSAM ------- CICSSHR.CICS004.ISE2WEB
IN-CAT --- UCAT.Z9CI01
NONVSAM ------- CICSSHR.CICS004.ISE22048
IN-CAT --- UCAT.Z9CI01
NONVSAM ------- CICSSHR.CICS004.ISE3CTG
IN-CAT --- UCAT.Z9CI01
NONVSAM ------- CICSSHR.CICS004.ISE32048
IN-CAT --- UCAT.Z9CI01
NONVSAM ------- CICSSHR.CICS004.JCLLIB
IN-CAT --- UCAT.Z9CI01
NONVSAM ------- CICSSHR.CICS004.JCLLIB.BK
IN-CAT --- UCAT.Z9CI01
NONVSAM ------- CICSSHR.CICS004.JOBLOG
IN-CAT --- UCAT.Z9CI01
NONVSAM ------- CICSSHR.CICS004.PGMSOR
IN-CAT --- UCAT.Z9CI01
NONVSAM ------- CICSSHR.CICS004.REXX
IN-CAT --- UCAT.Z9CI01
NONVSAM ------- CICSSHR.CICS004.USERLIB
IN-CAT --- UCAT.Z9CI01
NONVSAM ------- CICSSHR.CICS004.USERLIB2
PDSメンバー<=>USSファイルのコピー
こちらも、デフォルトの機能として、USSのシェルのcpコマンドで、USSファイルとMVSのPDSメンバー間でコピー操作ができます。
[CICS004@EPLEX1:/u/cics004/JCL] cp "//'CICSSHR.CICS004.JCLLIB(LISTC)'" listc2.jcl
[CICS004@EPLEX1:/u/cics004/JCL] cp listc2.jcl "//'CICSSHR.CICS004.JCLLIB(LISTCX)'"
MVSデータセットは、シングルクォーテーションでくくって、先頭に//を付けて、さらに全体をダブルクォーテーションでくくります。
これもUtilityで内部的に利用しています。
参考: z/OS UNIX ファイル・システムと MVS データ・セットとの間でのデータのコピー
ユーザー指定のJCLサブミット
よく、JCL実行時に、JOBパラメーターでUSER名指定でJCLサブミットすることがありますが、シェルから上のsumitJCL.sh使う場合は、その方法は使えません。基本的にsshでログインしているユーザー権限で実行されることになりますので、実行ユーザーを変えたい場合は、su でJCL実行したいユーザーにスイッチしてからサブミットして下さい。
パスワード変更
PCOMでTSOに入る時には、パスワードがExpireしていなくてもデフォルトでNew Passwordを指定する欄があります。
teratermからSSHで接続する場合には、ログイン時に新パスワードを指定する欄なんてありませんので、明示的にパスワード変更する場合は個別にコマンド叩く必要があります。
Unix系と同様にシェルからpasswd
コマンドで変更可能です。
$ passwd
Enter current password: *********
Enter new password: ********
Enter new password again: ********
弱点
基本、テキストしか扱えません。例えばJOBLOGとかに文字化けするようなデータが入っているような場合はうまく表示できません。当然HEXでの参照、入力もできません。
日本語(DBCS)は想定していないません。テストしきれていないですが色んな所で不具合出てくるでしょう。
データセット周りの操作は苦手です。PDSデータセット作成とかできません。
エディタはviだけだとやはり限界があるので、ゴリゴリ編集する必要があるのであれば専用のエディタを利用するのがよいでしょう。現時点ではEclipseベースのツール(z/OS Explorer, IDzあたり)が有力かと思いますが、最近だとZowe+VSCodeというのが私の中で大ヒットです。
応用編
z/OS上でのTCP/IPパケットトレース取得メモ
z/OSからSlackへのメッセージ送信
おわりに
ウィンドウサイズを気にせず沢山の情報を一度に表示したり、複数ウィンドウを並べて表示したり、必要な情報を抽出してファイルに落としたり、というように、Unixで当たり前のように使われているteraterm上の操作で、z/OS周りの操作がしやすくなるかと思います。
今回はユーザーがシェルから直接使う想定で作っていますが、シェル・スクリプトベースなので、出力フォーマットをもう少し加工すれば、自動化にも応用が利くと思います。USS上のシェル・スクリプトなので、SSH経由でリモートのオープン系との連携もできます。(なんでもかんでもREST APIじゃなくても、SSHで繋がれば結構いろんな連携できるんですよね。インフラ系は特に。)
ちなみにz/OSMFでは、テンプレートを元に決められたワークフローを流して環境の複製を自動化するようなプロビジョニング機能が提供されています。当ユーティリティでは、JCLテンプレート+プロパティファイルで、外から変数与えてJOB実行できるようにしていますが、これはz/OSMFのワークフローを意識して作りました。単純に変数置き換えしかできませんが、この辺りの操作がUSSシェルで実行できると、シェル・スクリプトでフローを書けるので、自動化の仕組みが断然作りやすくなります。
例えば、上のデモ動画で、CICSアプリのソース編集、資源定義辺りを個々のコマンドで実行しましたが、あの辺スクリプトにしてしまえば、ソース編集したら一発コマンド叩くだけでテストまで自動的に実行!、みたいなことに繋がると思います。しかも、製品/機能に特化した新しいスキルはあまりいらないのが利点です。
単純<=>複雑 / 機能:少<=>機能:多 辺りはトレードオフなのでどちらがよいかは状況次第ですが、製品提供機能はどうも重厚長大で機能過多になりがちな気がします。もちろん仕組みを自作してしまうとそれを自分でメンテナンスしなければならないということも出てくるのですが。その辺りは環境や要件を見極めて選択していくことになるでしょう。
※ということで当ユーティリティーの動作保証はしかねますので悪しからず。