REXXでは直接アプリケーションやユーティリティー・プログラムを呼び出して実行することもできます。非同期に実行されるバッチジョブのサブミットと異なり、REXX側の処理とアプリケーションやユーティリティーの処理を容易に同期させることができます。以下は、DFSORTのICETOOLユーティリティーを呼び出して実行するログラム・サンプルです。REXXからLINKMVSホスト・コマンドを使用しています。
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
/************************* REXX *************************** * REXX Exec with MVS, TSO and SDSF function under z/OS. * * ===================================================== * * SAMPLE FOR EXECUTING APPLICATION/UTILITY PROGRAM * ************************** REXX **************************/ /* define SORTCNTL/TOOLIN data list */ sortctl.0 = 2 sortctl.1 = " SORT FIELDS=(15,20,CH,A)" sortctl.2 = " SUM FIELDS=(11,4,PD) " toolin.0 = 7 toolin.1 = " SORT FROM(SYSUT1) TO(SYSUT2) USING(SORT) " toolin.2 = " DISPLAY FROM(SYSUT2) LIST(LISTOUT) - " toolin.3 = " TITLE('SALES RECORD LIST') DATE(4MD-) TIME PAGE -" toolin.4 = " HEADER('CUSTOMER NAME') HEADER('AMOUNT') - " toolin.5 = " ON(15,20,CH) ON(11,4,PD,A1) - " toolin.6 = " BLANK - " toolin.7 = " TOTAL('GRAND TOTAL') " /* allocate working dataset and build it */ ADDRESS TSO "ALLOC DD(DFSMSG) DUMMY REUSE" ADDRESS TSO "ALLOC DD(TOOLMSG) DUMMY REUSE" ADDRESS TSO "ALLOC DD(LISTOUT) DA(*) REUSE" ADDRESS TSO "ALLOC DD(SYSUT1) DA(SALES.DATA) SHR REUSE" ADDRESS TSO "ALLOC DD(SYSUT2) NEW DELETE UNIT(SYSALLDA) SPACE(1,1) TRACKS REUSE" ADDRESS TSO "ALLOC DD(SORTCNTL) NEW DELETE UNIT(SYSALLDA) SPACE(1,1) TRACKS REUSE" ADDRESS TSO "ALLOC DD(TOOLIN) NEW DELETE UNIT(SYSALLDA) SPACE(1,1) TRACKS REUSE" DROPBUF /* clear current stack */ DO ix=1 to sortctl.0 /* loop num of records from */ QUEUE sortctl.ix /* sortctl.1-x variables and */ END /* stack it to write PS dataset. */ QUEUE '' /* add null line to indicate eod */ ADDRESS MVS "EXECIO * DISKW SORTCNTL (FINIS" /* write it. */ DROPBUF /* clear current stack */ DO ix=1 to toolin.0 /* loop num of records from */ QUEUE toolin.ix /* toolin.1-x variables and */ END /* stack it to write PS dataset. */ QUEUE '' /* add null line to indicate eod */ ADDRESS MVS "EXECIO * DISKW TOOLIN (FINIS" /* write it. */ /* call DFSORT/ICETOOL */ pgm = 'ICETOOL' ADDRESS LINKMVS pgm SAY SAY "==================================" SAY "LINKED MVS Program="pgm", RC="rc /* unallocate working dataset */ ADDRESS TSO "FREE DD(DFSMSG)" ADDRESS TSO "FREE DD(TOOLMSG)" ADDRESS TSO "FREE DD(LISTOUT)" ADDRESS TSO "FREE DD(SYSUT1)" ADDRESS TSO "FREE DD(SYSUT2)" ADDRESS TSO "FREE DD(SORTCNTL)" ADDRESS TSO "FREE DD(TOOLIN)" |
REXXからMVSプログラムを呼び出すこと自体は、ADDRESS LINKMVS “pgmname arg1 arg2 …”と記述するだけなので簡単ですが、元々JCLを使用したバッチジョブとして実行していたものについてはDDステートメントの記述に相当する部分をREXX内で行わねばなりません。このサンプルでも同じですが、プログラムの呼び出しそのものよりは、TSOのALLOCATEとFREEコマンド、DD *ステートメント内へのユーティリティー制御ステートメントの記述に相当する処理(ステートメント内容の記述とEXECIOでの割り振り済みデータセットへの出力)が大半を占めています。
以下が、ISPFコマンドシェルから実行した結果です。ユーティリティーの実行結果が出力されるDD名LISTOUTにはTSO端末を割り当ててあるので、自分でSAY命令で出力しなくてもTSO端末(バッチセッションの場合はSYSOUT)に直接リダイレクトされます。プログラムからの出力内容が表示されてから「ADDRESS LINKMVS pgm」の後に記述したSAY命令の出力が表示されていることで、プログラムが同期呼び出しされていることがわかります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
SALES RECORD LIST 2021-07-07 22:50:47 - 1 - CUSTOMER NAME AMOUNT -------------------- -------------------- ABC-COMPANY 2,491,166 BOND STORE 1,534,309 GREAT MARINE SERVICE 2,478,821 KK OIL-COMPANY 1,638,419 MICHELLE CO,LTD. 798,017 MM-CORPORATION 810,362 RED-COMPANY 1,742,529 WBLACK-COMPANY 798,017 WHITE-MOTORS 61,725 GRAND TOTAL 12,353,365 ================================== LINKED MVS Program=ICETOOL, RC=0 *** █; |
実践向けの改良
上記で示したサンプルではアプリケーションやユーティリティーからの出力を直接TSO端末にリダイレクトしてしまっているので、このままではJCLでサブミットすることと大差ありません。REXXからプログラムを呼び出す主な目的は処理の自動化であったり、出力結果の解析や加工などでしょう。下記に、プログラムからの出力をREXX内で読み込み解析や加工ができるように改修したサンプルも紹介します。このサンプルではプログラムからの出力内容は自動的に端末にリダイレクトされませんから、「ADDRESS LINKMVS pgm」の後に記述したSAY命令の出力が先に表示されていることがわかります。
LISTOUTデータセットを端末ではなく一時データセットに割り当てて、プログラム実行後にLISTOUTデータセットの内容をEXECIOで読み込むようにしたものです。サンプルでは読み込んだレコードをSAY命令で表示していますが、実際の処理ではここで文字列の解析などを行うことになります。なお、最後の2行で行っているLISTDSIとISPFブラウザーでの表示は実際には不要な処理です。一時データセットの内容をISPFブラウザーで表示するには、実際のDSNと格納VOL名が必要になりますが、それを取得するためのLISTDSI関数を使ったサンプルとして追加しました。デバッグ目的でプログラムからの出力内容を直接見たいような場合に利用できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
: /* ADDRESS TSO "ALLOC DD(LISTOUT) DA(*) REUSE" */ ADDRESS TSO "ALLOC DD(LISTOUT) NEW DELETE UNIT(SYSALLDA) SPACE(1,1) TRACKS REUSE" : : /* call DFSORT/ICETOOL */ pgm = 'ICETOOL' ADDRESS LINKMVS pgm SAY "LINKED MVS Program="pgm", RC="rc SAY "==================================" SAY ADDRESS MVS "EXECIO * DISKR LISTOUT (FINIS" /* read result. */ DO QUEUED() /* loop num of records in stack */ PARSE PULL record /* pull record from stack and */ SAY STRIP(record) /* show it without trailing blank. */ END x=LISTDSI('LISTOUT FILE') ADDRESS ISPEXEC "BROWSE DATASET('"sysdsname"') VOLUME("SYSVOLUME")" : |
以下が、実行した結果です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
LINKED MVS Program=ICETOOL, RC=0 ================================== 1SALES RECORD LIST 2021-07-10 23:12:51 - 1 - CUSTOMER NAME AMOUNT -------------------- -------------------- ABC-COMPANY 2,491,166 BOND STORE 1,534,309 GREAT MARINE SERVICE 2,478,821 KK OIL-COMPANY 1,638,419 MICHELLE CO,LTD. 798,017 MM-CORPORATION 810,362 RED-COMPANY 1,742,529 WBLACK-COMPANY 798,017 WHITE-MOTORS 61,725 GRAND TOTAL 12,353,365 *** █; <ここで実行キーを押せばISPFブラウザーが起動され、ICETOOLからの出力内容が表示される> |