以前にUSSシェルからZOAU(*1)を利用することでMVS側の様々なリソースにアクセスできることを紹介しました。しかし、同様のことはREXXとSDSFの組み合わせでとっくの昔にできていました。ここでは視点を変えてUSS側からのPython+ZOAUではなく、MVS側のコマンドシェルであるTSOからのREXX+SDSFで同様の処理を行う方法を紹介します。併せてUSS側からMVS側のREXXを実行する方法も紹介します。
*1 シェル・コマンドやPythonやJavaなどからのAPIコールによって、USS側から容易にMVS側リソースにアクセスできる機能。
REXXでは外部(環境)コマンドによってMVSデータセットにアクセスすることができます。以下は、MVSデータセットの内容を読み込んで別のデータセットにコピーするプログラム・サンプルです。データセットのアクセスには、TSOコマンドのALLOCとFREE、MVSホスト・コマンドのEXECIOを使用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
/************************* REXX **************************/ /* REXX Exec with MVS, TSO and SDSF function under z/OS. */ /* ===================================================== */ /* MVS DATASET I/O SAMPLE. */ /************************* REXX **************************/ /* allocate input and output dataset */ ADDRESS TSO "ALLOC DD(IN) DA(WORK(MSG1)) SHR REUSE" ADDRESS TSO "ALLOC DD(OUT) DA(WORK(MSG2)) SHR REUSE" /* read and write the dataset */ ADDRESS MVS "EXECIO * DISKR IN (FINIS" /* read all records into stack */ QUEUE '' /* add null line to indicate eod */ ADDRESS MVS "EXECIO * DISKW OUT (FINIS" /* write all records from stack */ IF SYSVAR("SYSENV") = 'FORE' /* show output dataset using ISPF browser when run under TSO foreground session */ THEN ADDRESS ISPEXEC "BROWSE DATASET(WORK(MSG2))" ELSE ADDRESS MVS "EXECIO * DISKR OUT (FINIS" DO QUEUED() /* loop num of records in stack */ PARSE PULL record /* pull record from stack and */ SAY record /* show it. */ END /* un-allocate input and output dataset */ ADDRESS TSO "FREE DD(IN)" ADDRESS TSO "FREE DD(OUT)" EXIT 0 |
REXXのEXECIOはDDステートメントに対するデータセット入出力機能なので、最初にデータセットをアロケーションしておく必要があります。ADDRESS TSOでALLOCコマンドを実行し、入力側と出力側のデータセット(PDSメンバー)をそれぞれINとOUTのDD名で割り振っています。データセットを割り振れば、後はADDRESS MVSでEXECIOを実行すればデータセットにアクセスできます。EXECIOのDISKRではデータセットのレコード内容はスタックに格納されますので、その内容をそのままDISKWで別データセット(別メンバー)に書き出しています。
以下が、ISPFコマンドシェルから実行した結果です。TSOのフォアグラウンド・セッションで実行された場合は、コピーされた出力側のデータセット内容をISPFブラウザーを起動して表示しています。REXXならISPFユーティリティーの呼び出しも簡単です。
TSO端末(ISPFコマンド・シェル)ではなくバッチジョブとして処理する場合は、下記のようなJCLで実行できます(*2)。
*2 サンプルは標準のTMPであるIKJEFT01を使用しているが、他にもIRXJCLを使用する方法もある。詳細は「z/OS TSO/E REXXユーザーズ・ガイド」を参照。
1 2 3 4 5 6 7 8 9 |
// JOB //********************************************************************* //BUILDSRC EXEC PGM=IKJEFT01 //SYSTSPRT DD SYSOUT=* //SYSEXEC DD DISP=SHR,DSN=&SYSUID..CLIST //SYSTSIN DD * %REXXDSIO // // |
以下は、TSOのバッチセッションから実行した結果です。ISPFブラウザーを起動する代わりにコピーされた出力側のデータセット内容を読み込んでSAY命令で標準出力(TSOの場合はSYSTSPRT)に表示しています。あくまでもTSOフォアグラウンド時のISPFブラウザー起動の代わりとしてサンプル用に追加した処理なので、実際に行う必要はないでしょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
SDSF OUTPUT DISPLAY jobname JOB09757 DSID 102 LINE 1 COLUMNS 02- 133 COMMAND INPUT ===> SCROLL ===> CSR READY %REXXDSIO AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC 44444444444444444444444444444444444444444444444444444444444444444444444444444444 77777777777777777777777777777777777777777777777777777777777777777777777777777777 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ READY END ******************************** BOTTOM OF DATA ******************************** |
<USSからMVS REXXを実行する>
USSシェル内でもREXXを実行することはできますが、MVSホスト・コマンドを実行できないためMVS側で実行した時と同様の処理はやりにくいです。TSOコマンドは実行できるので、REXXをUSSシェル内ではなくMVS側のTSOバッチセッションとして実行させることができます。この方法ならREXXはMVS側環境で実行されるため、MVSリソースに直接アクセスできます。下記のREXXサンプルdorexxは、MVS側のライブラリーに格納されているREXX execを、MVS側のTSOバッチセッションで起動されるようUSSシェルからキックするものです。dorexx自体はUSSシェル内で実行されますが、dorexxから起動するREXX execはMVS側のアドレス空間で実行されます。
1 2 3 4 5 6 7 8 9 10 11 12 |
BROWSE /u/userid/dorexx Line 0000000000 Col 001 055 Command ===> Scroll ===> CSR ********************************* Top of Data ********************************** /* REXX */ /* Do REXX exec under MVS TSO BATCH TMP environment. */ /* SYSTSPRT route to STDOUT */ parse arg var1 dsname = "EX 'userid.CLIST("var1")'" say "Do REXX exec under MVS TSO Batch environment." address TSO dsname say "TSOCMD="dsname", RC="rc ******************************** Bottom of Data ******************************** |
以下が、USSシェルからdorexx経由でMVS側REXXを実行した結果です。MVS側で実行したSAY命令の出力は、USSシェル側の標準出力(STDOUT)にリダイレクトされます。
1 2 3 4 5 6 7 8 9 10 11 12 |
/u/userid > dorexx rexxdsio Do REXX exec under MVS TSO Batch environment. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC 44444444444444444444444444444444444444444444444444444444444444444444444444444444 77777777777777777777777777777777777777777777777777777777777777777777777777777777 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ TSOCMD=EX 'userid.CLIST(rexxdsio)', RC=0 /u/userid > |
USSシェル内でもREXXそのものを実行することができるので、主たる処理もUSS側のREXXで行うか主たる処理はMVS側で行うかは、それぞれの利用者が自身にとって最適なものを選択すればいいでしょう。USSシェルをメインにしてz/OSを操作するのであれば、REXXよりもPythonやJavaあるいはシェル・スクリプトが適している場面も多いでしょうし、逆にMVS側のTSO(ISPFやSDSF)をメインにしてz/OSを操作するのであれば、REXXはとても強力なツールですし場合によってはCLISTでも十分なケースもあります。いずれにせよ、特定の使い方に固執せずに適材適所で柔軟な使い分けができるようになるといいでしょう。