JCL(Job Control Language:ジョブ制御言語)はz/OSを始めとする、MSP、VOS3、VSE、XSPなど多くのメインフレームOSにおいて、ジョブを定義するために使われるものです。言語となっていますが、スクリプトに近い物で、Windowsのバッチファイル(.bat)、UNIXのシェルスクリプト(.sh)に相当します。バッチファイル(シェルスクリプト)は複数のプログラムやコマンドを連続して実行したり、自動で実行したりするためによく使われますが、メインフレームのJCLでもそれは同じです。しかしメインフレームのJCLではジョブが使うコンピュータ資源を割り振る、と言うもう一つの重要な側面を持ちます。
またジョブの定義とは、ジョブが行う処理(ジョブ・ステップ)と使うリソース(ジョブ・リソース)を明確にすることです。z/OS(MSP,VOS3)ではジョブはJCLの3つのステートメントによって定義され、運用(実行)されます。
JCLの例
—-+—-1—-+—-2—-+—-3—-+—-4—-+—-5—-+—-6—-+—-7–
//jobname JOB (account),name,CLASS=A,MSGCLASS=B
//JOBLIB DD DISP=SHR,DSN=USR1.LINKLIB
//*********************************************************************
//STEP1 EXEC PGM=GHY76R5
//PRINT DD SYSOUT=*
//DATAIN DD DISP=SHR,DSN=GHY.M78D543.MASTER
//OUTPUT DD DISP=(,PASS),DSN=&&WORK,UNIT=SYSDA,SPACE=(TRK,(10,10))
//*
//STEP2 EXEC PGM=STU38AZ,PARM=’PICKUP=(2,8,65)’
//SUMMARY DD SYSOUT=*
//INPUT DD DISP=(OLD,DELETE),DSN=&&WORK
//OUTPUT DD DISP=OLD,DSN=GHY.M78D543.UPDATE
//CONTROL DD *
001-005: NAME
010-060: ADDRESS
//
JCLは先頭が//で始まる1行80桁のレコードが、複数集まって構成されます。複数集まったJCLレコードが入力ストリームまたはジョブ・ストリームです。
JCLに限らずメインフレームの多くの制御データには80バイト(80桁)を基本にしたものが数多く存在します。ソースプログラムもディスプレイ端末の横幅も80バイトが基本になります。これはメインフレーム・コンピュータの前身である、タビュレーティング・マシンやパンチカードシステムで利用された紙カードと言う記憶媒体の名残です。
構文の基本
レコードは80バイトですが、先頭の1~71桁目までを使用します。72桁目は行継続のために使用する予約桁です。73桁目以降はJCLとしては使われません。ステートメントの順番を管理するためのSEQフィールドとして利用するか、空白にしておきます。
先頭の//は必須で、この2文字(IDフィールド)がレコードそのものがJCLステートメントであることを示します。//に続き名前、命令、オペランドが記述されます。名前、命令、オペランドの各フィールドは1文字以上の空白によって区切られます。オペランド・フィールドには命令に対するパラメーターが記述されます。複数のパラメーターがあるときは空白ではなくカンマで区切ります。最後のパラメーターの後ろに1文字以上の空白を置けば、以降行末までコメントを記述することができます。行全体をコメントにする場合は//*と記述して、4桁目以降に任意のコメントを記述します。
—-+—-1—-+—-2—-+—-3—-+—-4—-+—-5—-+—-6—-+—-7–
//name1 op parm1=value1,parm2=(value2a,value2b) comment…..
//name2 op parm1=value1,parm2=(value2a,value2b),parm3=value3,
// parm4=value4,parm5=value5
JOBステートメント(ジョブを示す)
JOBステートメントはジョブそのものを定義します。名前フィールドに指定されたものがジョブ名となります。パラメーターはJOB全体の制御に関する物で、アカウントに関するもの、実行するためのクラス識別子、ジョブログの出力クラス識別子、ジョブに与えるストレージサイズなどで構成されます。
EXECステートメント(ジョブ・ステップを示し、動かすプログラムを指定する)
EXECステートメントはジョブ・ステップを定義します。名前フィールドに指定されたものがステップ名となります。パラメーターはステップで実行するプログラムおよびプログラムの制御に関する物で構成されます。実行するプログラム名(PGM=)や、プログラムへ渡すパラメーター(PARM=)、利用可能なCPU時間(TIME=)や先行ステップの終了状況に応じた条件付き実行制御のためのパラメーター(COND=)などがあります。
ジョブ・ステップはEXECステートメントで定義された順序で、一つずつ順番に実行されます。z/OSとMSPではIFステートメント等を使ってステップの実行をより細かくコントロールすることもできます。ただしIFやDOのように後から拡張された機能にはメーカー間での互換はなく、各OSそれぞれが独自の機能として実装されています。
DDステートメント(ステップで使うデータなどを指定する)
DDステートメントはステップで使用するコンピュータ上のリソースを定義します。名前フィールドに指定されたものがDD名(リソース名)となります。ここで定義するリソースはデータセットやボリュームなど、プログラムがアクセスするデータないしはデバイスが主なものになります。メインフレームではデータを格納したファイルの名前を直接プログラム内に持つことはありません。基本的にはプログラムはデータにアクセスする際、リソース名(DD名)を使い、JCLのDDステートメントを介して、ターゲットのデータセットなどと実行時に結びつけられます。メインフレームでは多くの場合、データセット(ファイル)をアクセスする際、それが新規のものか既存のものか、どのボリュームに作成するのか、上書きするのか追加するのかなど、データの運用に関することはプログラムではなく、JCLによってコントロールできるようになっているのが特徴です。
空白ステートメント
//のみのステートメントはジョブの終わりを示します。JCLの終わりではないことに注意して下さい。//のみのステートメントの後に、次のJOBステートメントがあれば、引き続きそのJOBが解釈され実行されます。ただし//のみの後、次に新たなJOBステートメントがくるまでのカードはすべて無視されます。
//JOB1 JOB CLASS=A,MSGCLASS=B
//STEP1 EXEC PGM=……..
//
//STEP2 EXEC PGM=…….. ——+
//SYSUT1 DD DISP=SHR,DSN=…….. +–> 無視される
// ——+
//JOB2 JOB CLASS=A,MSGCLASS=B ここから新たなジョブ、JOB2として解釈される
//STEP1 EXEC PGM=……..
ストリーム内データセット
通常データはDASDやテープなど、外部記憶上のデバイスに保管されていますが、パラメーターなどプログラムに動作内容を指示したりするための、比較的少量のデータに関しては、JCL内に直接記述することもできます。DDステートメントに*パラメーターを記述することで、80バイト固定長レコードのデータセットをJCL内に簡単に定義することができるようになっています。ただし入力専用となります。バッチジョブにおける標準入力装置(stdin)に相当すると考えてもいいでしょう。
ユーティリティ・プログラムの実行制御パラメーターなどは、たいていの場合、このストリーム内データセットによってJCL内に直接定義されます。SYSINデータセットとも呼ばれますが、多くのユーティリティ・プログラムの実行制御文がDD名SYSINで定義されたことからの慣例です。
SYSOUTデータセット
入力専用のストリーム内データセット(SYSIN)に対して、出力専用のデータセットも定義できます。DDステートメントにSYSOUTパラメーターを記述することで、OS(JES2)のスプール内に仮想の順次データセットを作成することができます。SYSINと異なり、レコード形式や長さはプログラムで任意に指定することができます。こちらはバッチジョブにおける標準出力装置(stdout)に相当すると考えてもいいでしょう。
たいていの場合SYSOUTデータセットはプログラムの処理結果を印刷するためのリストファイルとして使われます。メインフレームのプログラムで処理結果をプリンターで印刷する場合、プログラムが直接プリンター・デバイスにアクセスすることはありません。SYSOUTと言う仮想のデータセットに印刷データを出力することで、間接的にプリンターを利用します。この場合の印刷はバッチジョブによる、バッチ処理の印刷です。オンライン処理における印刷はSYSOUTではなく、CICSやIMSなどオンラインシステム用ミドルウェアなどの機能を介して行われます。
プロシージャ
プログラムにもサブルーチンがあるように、よく使うジョブ・ステップや使用するデータを変えて繰り返し実行するステップは呼び出して実行させることができます。呼び出されるジョブ・ステップの集まりをプロシージャと呼びます。サブルーチン同様にパラメーターを引き渡すこともできます。プロシージャには定められたJCLライブラリに登録されるカタログ式プロシージャと、JCL内に直接定義して使うストリーム内プロシージャがあります。複数のジョブから共通に利用されるならばカタログ式プロシージャ、特定のジョブ内で繰り返し実行されるステップの定義にはストリーム内プロシージャ、と使い分けられることが多いです。
// JOB CLASS=A,MSGCLASS=B
//*
//MTCOPY PROC NAME=,LBL= ————–+
//IEBGENER EXEC PGM=IEBGENER I PROC~PENDで
//SYSPRINT DD SYSOUT=* I 囲まれた部分が
//SYSUT1 DD DISP=SHR,DSN=&NAME I プロシージャとなる
//SYSUT2 DD DISP=(,CATLG),DSN=&NAME..BKUP, I
// UNIT=TAPE,VOL=(,RETAIN,,10),LABEL=&LBL I
//SYSIN DD DUMMY I
// PEND ————–+
//*
//STEP1 EXEC MTCOPY,LBL=1,NAME=’MY.DATASET1′ プロシージャの呼び出し
//STEP2 EXEC MTCOPY,LBL=2,NAME=’MY.DATASET2′ プロシージャの呼び出し
//
JCLにおいてはJOB,EXEC,DDの各ステートメントが基本となります。それぞれジョブ、ステップ、データリソースを定義します。SYSIN/SYSOUTはジョブの入出力に利用する仮想のデータセット、共通で利用したり、繰り返し実行する部分はプロシージャとして定義する、と言う基本を踏まえ、実践で使うJCLを作成したり、修正してみてください。細かなパラメーターやその他のステートメントなどはマニュアルに載っています。 以上JCLのほんのさわりについて解説しました。
たかが1つのプログラムを動かすのにもMVSではいちいちJCLを作らねばなりません。でもTSOならコマンドとして動かせるじゃないか?と思ったかも知れません。それでもTSOユーザーとしてログオンするためにログオン・プロシージャと呼ばれるJCLが裏では動きます。使うユーザーが自分で意識しなくても、見えないどこかで必ずJCLは使われます。オンライン処理でデータベースを使うようなことであっても、IMSやCICS、DB2など多くのミドルウェア製品自体がJCLによって、MVS上で動いています。WindowsやUNIXなど他のコンピュータ・システムで慣れた人には面倒に思えます。この理由は歴史的な経緯から来ています。初期のコンピュータではメモリーはとても小さな物で、1つのプログラムを大きくすることはできませんでした。今では想像もできませんが、せいぜい数キロバイトから数十キロバイトしかなく、仮想記憶すらなかったのです。そこで行うべきな仕事をいくつもの作業や処理に分けて分割することで1つ1つのプログラムが小さくなるようにしていました。それらを必要な順序で、必要なデータを読み書きさせることで1つの仕事(ジョブ)をこなすように考えられました。オペレーターは紙カードやテープを装置に掛けてデータを準備し、自らプログラムをメモリーに読み込ませ、実行することでコンピュータ処理を行っていました。この時に使われるのがプログラマーからオペレーターへのオペレーション指示書です。いちいち人間の手作業が入るので効率は上がりません。そこでオペレーション指示書に相当するJCLが採用され、プログラマーからOSに何をすべきか直接指示できるようにしたわけです。数多くの仕事を人間が介在しなくても、定められた順序で次から次へとこなして、大量のデータを自動的に処理するため、メインフレームではJCLは大きな役割を果たしており、40年以上も経った現在でもほとんど初期の実装のまま使われ続けています。
次回はMVSがJCLによって定義されたジョブを実行するしくみである、ジョブ管理とJES2についてお話しします
コメント
投稿にはログインしてください