Job Control Language

Job Control Language（JCL、ジョブ制御言語）とは、メインフレームコンピュータの一部のオペレーティングシステムで使用されているジョブ制御用の指示言語である。通常はJCLを使用してジョブ名や、そのジョブで使用するプログラムやファイル（データセット）などの指定を行う。
オペレーティングシステムによってはJCS(Job Control Statement)、ECL（Executive Control Language）、WFL(Work Flow Language)とも呼ばれ、その構文や機能も異なるが、当記事ではこれらも含めて記載する。

**概要**
ジョブ制御言語（JCL）は正確には、メインフレームのオペレーティングシステムに含まれるジョブ管理システム（ジョブ入力サブシステム）に対して、バッチ処理や常駐プロセス起動時の指定をするスクリプト言語である。ジョブ制御言語（JCL）では通常、ジョブ名（ジョブID）、１つまたは複数の実行するプログラム、使用するファイル（データセット）などを指定する。JCLは、UNIXやLinuxなどの実行モジュール起動用のシェルスクリプトに似ているが、JCLはプログラムの実行やファイル名の指定に必須である。
オペレーティングシステムやそのバージョンにより機能や構文は異なるが、JCLを持つ主なOSには以下がある。
*MVS系
**IBMのMVS系（起源はHASP、JES2となり、MVSでOS標準化、現在はz/OS。JCL中のジョブ管理は厳密にはJECL(Job Entry Control Statement)）
**富士通のOSIV/MSP（MVS互換だが独自拡張あり）
**日立製作所のVOS2, VOS3（MVS互換だが独自拡張あり）
*IBMのVSE系（起源はDOS用POWER、最終はz/VSE。名称はJCS(Job Control Statement)で機能・構文もMVS系とは異なる）
*富士通のXSP（機能・構文もMSPとは異なる）
*GCOS系（多機能で一般のシェルスクリプトに近い）
**BullのGCOS
**日本電気のACOS-2, ACOS-4, ACOS-6
*ユニシスのOS2200系 (名称はECL(当初は Exec Control Language, 現在は Executive Control Language)
*ユニシスのMCP系 (名称はWFL(Work Flow Language))
なおメインフレームでも以下のOSや環境にはJCLは存在しない。
*IBM z/VM
*UNIX, Linux およびz/OSのUSSなどのUNIX環境

**MVS系のJCL**
JCLは、バッチ処理をどのように動かすか、サブシステムをどのように起動させるかを、ジョブエントリーシステム（Job Entry Subsystem 2/3、JES2 または JES3）に対して指示するものである。
JCLの各行の先頭2文字は、"//" で始まる。このスラッシュは、パンチカードを使ってJCLを読み込ませジョブを投入していたときの名残である。誤ってパンチカードを後ろからカードリーダーに挿入してしまった場合（代わりにシーケンス番号が先頭に来ることになるだろう）、リーダーは "//" が先頭にないことを読み取って、そのカードを拒絶するようになっていた。
互換性（上位互換、下位互換）のために、z/OS で使う JCL の文法は、1960年代から基本的には変わっていない。OS/360 で動いたものと同じ JCL が z/OS でも動いている。

**文法**
JCL ステートメントの1行の長さは80バイトで、1行またはそれ以上のステートメントで1本の JCL が構成される。
JCL ステートメントは1カラム目から71カラム目までを使用する（コメントは除く）。73カラム目から80カラム目は、しばしばシーケンス番号が記述される。
71文字を超えて1つのステートメントを記述する場合には（コメントは除く）、先の行の最後はカンマで終わり、次の行は4カラム目から16カラム目の間から始める（もちろん、全ての行の先頭2文字は "//" である）。

**Identifierフィールド、Identifier欄**
JCLは、1カラム目から2カラム目の "//" から始まる。下記を除く：
*"/*" もしくはユーザー定義の別の delimiter
*"//*" は、その行全てがコメントであることを指示する。

**名前フィールド、名前欄**
名前フィールドは、1つのステートメントである。だから、他のステートメントがそのステートメントを指し示す・言及することができる。3カラム目から始まり、8文字以内の長さでなければならない。アルファベットと数字、"#" や "@" や "$" などの文字が使用できる。名前の先頭は、数字であってはならない。ジョブ名、ステップ名、プロシージャ名、DD名を記述する。

**オペレーションフィールド、オペレーション欄**
オペレーションフィールドは、実行すべきコマンド、オペレーション（"JOB"、"EXEC"、"DD" など）を記述する。少なくとも1文字の空白が先におかれなければならない。

**パラメータ/オペランドフィールド、パラメータ/オペランド欄**
キーワードパラメータの順序は決まっていない。パラメータとパラメータの間に空白は置かない。空白の後はコメントになる。行内のパラメータの記述の左側、パラメータの前には、可読性を高めるための空白が入る。

**コメントフィールド、注釈欄**
JCL のステートメントのパラメータフィールドの後ろにインラインコメントを記述する場合には、少なくとも1文字の空白を入れてステートメントとコメントを分ける。71カラム目を超えてコメントを記述する場合には、72カラム目を空白にしない（通常、"X" が使われる）。次の行は "// " の後1カラム目から3カラム目の間からコメントの記述を続ける。

**ジョブ**
1つのジョブ(JOB)はジョブステートメント（ジョブ文）で始まり、 "//" だけの空行（空文）で終わる。1つのジョブ(JOB)の中の各々のステップ(STEP)は、1つのエグゼキュート(EXEC)ステートメント（EXEC文）と複数のデータディファニッション(DD)ステートメント（DD文）、各々のDDステートメントに1つのアクセスするデータセットで構成される。

**JOB文**
//jobname JOB (accounting information),CLASS=x,MSGCLASS=x,REGION=nK,TIME=(m,s),NOTIFY=XXXXXX
CPU や I/O など、コンピュータ資源を使用した分の使用料を使用した部署に請求するために、必要な会計上の情報が、カッコやクオーテーションマークで区切られて記述される。
CLASS パラメータは、ジョブがどのイニシエータで走るかを決める。その他、ジョブの優先度を指定するパラメータなどがある。
MSGCLASS パラメータはジョブの実行結果をどこに出力するかを指定する。出力クラスは個別のプリンタや、指定のファイルなどに割り振られていて、ユーザーは希望の出力先を指定する。
REGION パラメータは、ジョブが使用できる仮想記憶の最大量、リージョンのサイズを決める。キロやメガという単位を用いて指定できる。指定できる大きさは、システムを構築するときにジョブクラス毎に設定される。
TIME パラメータは、CPU を使用できる最大時間を決める。分、秒で指定する。ジョブの全てのステップが使用する時間を指定する。使用できる最大時間は、1439分59秒（TIME=(1439,59)）。1440分を指定すると時間制限なしとなる。

**EXEC PGM文**
//stepname EXEC PGM=progname,PARM="parm",COND=condition,REGION=nK,TIME=(m,s)
progname は、実行するプログラムを指定する。プログラムがシステム標準指定のリンクリスト、ライブラリに無い場合、JOBLIB か STEPLIB を DD ステートメントに記述して、格納してあるライブラリを指定する。
COND パラメータは、条件を満足する場合は当該ジョブステップを迂回する、実行しない、という指定である。このパラメータはしばしば、条件を満足したら通る、実行する IF ステートメントと混同され、混乱を招く。最近リリースされたオペレーティングシステムでは、この COND 指定の記述法は IF 指定の記述法に置き換わっている。

**EXEC PROC文**
//procstepname EXEC PROC=procname,param1=foo, ...
または
//procstepname EXEC procname,param1=foo, ...
procname は、カタログされた、あるいは in-stream （流れ内）のプロシージャ名を指定する。param1 以下の指定は、プロシージャに定義されたシンボリックキーワードに依る。プロシージャは、予め定義された JCL（の集まり）である。慣例上、上記例の2つめ、「PROC=」を省いた形を用いる場合が多い。

**DD文**
//ddname DD DSN=datasetname,DISP=disposition,UNIT=unit,VOL=SER=volser,SPACE=space,DSORG=dsorg,DCB=dcb
または
//ddname DD または
//ddname DD DATA,DLM=@@
または
//ddname DD SYSOUT=msgclass
DSN パラメータには、アクセスまたはアロケートするデータセット名を指定する。そのデータセットがカタログされていない場合、さらに UNIT パラメータと VOL パラメータが必要である。区分データセットの中の1つのメンバーを参照・指定・言及する場合には、カッコで括って記述する。たとえば MY.LIBRARY(MYPROGRM) というように。もしデータセット名を指定しなかった場合は、システムは1つ、データセットを割り当てる。このデータセットは当該ステップの中でのみ維持され、使用できる。ステップを跨って使用するが、ジョブが終了したら不要な一時データセット、テンポラリデータセットを指定するときは、データセット名の先頭に「&&」を記述する。たとえば DSN=&&TEMPNAME のように。
DISP パラメータは、データセットをそこで作成するのか、既に存在するのか、ジョブが正常終了したときデータセットを保存しておくのか消してしまうのか、ジョブが失敗に終わったときにデータセットを保存しておくのか消してしまうのか、を指定する。この DISPOSITON パラメータは、カッコで括って3つのサブパラメータがある。例：
*DISP=(OLD,DELETE,KEEP) － データセットは既存で、ステップが成功したら削除され、失敗したら保存される。
*DISP=SHR － データセットは既存で、同じタイミング、時刻に別のタスクが読みに来るかもしれない場合。
*DISP=(NEW,CATLG,DELETE) － データセットを新規に作成し、カタログする。ステップが失敗したら、削除されカタログははずされる。
なにも指定しない場合の初期値は (NEW,DELETE) である。
UNIT パラメータと VOL パラメータは、併せて記述できる。しかしここでは、シンプルな記述例を示す：
*UNIT=SYSDA － ダイレクトアクセスデバイス全般を意味する。テンポラリファイル（一時データセット）への指定の場合が多い。
*UNIT=3390,VOL=SER=ABC123 － 特定の（指定の）ダスドのパック ABC123 にアロケーションすることを指定。
SPACE パラメータは、ブロック、トラック、シリンダー単位で、1次割り振り量と2次割り振り量を指定する。および、区分データセットのディレクトリブロックの大きさを指定する。例：
*SPACE=(TRK,1) － 1トラックだけ割り振る。2次割り振りはしない。
*SPACE=(CYL,(50,25)) － まず最初に50シリンダー割り振り（1次割り振り）、足りなければ25シリンダーを15回まで割り振っていく（2次割り振り）。（それでも足りなければ容量不足でジョブは異常終了する）
*SPACE=(4096,(10000),ROUND,RLSE) － 4096バイトのブロックが10000ブロック分になるように、シリンダーのサイズに近い値で割り振る。使わない余ったスペースが生じたら、ジョブステップが終了したときに空き部分を解放する。
DSORG パラメータは、データセットの編成方法を指定する。PS（物理順次、順次データセット）か、DA（ダイレクトアクセス）か、IS（ISAM、現在はサポートされていない）か、PO（区分データセット）を指定する。
DCB パラメータには、プログラムがデータコントロールブロックにてこの DD ステートメント宛てに指定したどのサブパラメータも指定できる。通常は、RECFM サブパラメータによって、レコードフォーマットが指定されることが多い。FB（ブロック化された固定長）、U（未定義）、V（可変長）など。
DD * は、そこから先は80バイトのカードイメージのデータである、という指定である。このデータは、1カラム目から2カラム目に /* と記述するか、次のJCLステートメント（1カラム目から2カラム目が "// " ）の記述が始まることで終了する。（この記法は一種のヒアドキュメントとも考えられる）
DD DATA は、DD * と同じだが、JCL ステートメントに含まれる。それは、1カラム目から2カラム目に @@ が記述される行または JCL の終了をもって終了される。
DD SYSOUT=msgclass は、プリントを出力する先を指定する。 SYSOUT=* と指定すると、ジョブカードに指定した MSGCLASS に出力される。
入力データ用の DD ステートメントは、下記のように連結して指定できる（コンカチ）。
//STEPLIB DD DSN=MY.TEST.LIBRARY,DISP=SHR
//        DD DSN=MY.TEAM.LIBRARY,DISP=SHR
//        DD DSN=MY.LIVE.LIBRARY,DISP=SHR

**プロシージャ**
プロシージャは、JCL のスケルトンである。通常、置き換えることでデータセット名を指定できるようなシンボルを含む。これらのシンボル名は、プロシージャが実際に使われるときに、本当のデータセット名に置き換わる。プロシージャは、JCL にマクロ機能を可用にする。
MVS の古いバージョンでは、プロシージャは SYS1.PROCLIB に予め格納/カタログされていなければならなかった（カタログ式プロシージャ、カタプロ）。新しいバージョンでは、ユーザーが定義したライブラリに格納したプロシージャも使えるようになった。
通常、プロシージャは、上記のような proclib と称されるプロシージャライブラリから呼び出されて実行される。一方、実行するそのジョブそのものの中に定義することもできる。これは流れ内 (inline, in-stream) プロシージャと呼ばれ、普通は、proclib に登録する前にプロシージャをテストする際に用いられる。
最初の行は必ず PROC ステートメントで始まる。そこにはプロシージャ名と、シンボリックの初期値を定義する。例：
//MYPROC  PROC &LIB="MY.TEST.LIBRARY"
あるジョブがこのプロシージャをコールするとき、たとえば以下のように記述する:
//FIRST       EXEC MYPROC
//SECOND  EXEC MYPROC,LIB="FREDS.TEST.LIBRARY"
FIRST の例では、MYPROC プロシージャ中のシンボル LIB は初期値 "MY.TEST.LIBRARY" に置換される。SECOND の例では、MYPROC プロシージャ中のシンボル LIB はコール時に指定した "FREDS.TEST.LIBRARY" に置換される。
流れ内プロシージャを終了するステートメントは:
//     PEND

**条件処理**
JCL は、if-then-else-endif ステートメントを用いた初歩的な条件処理をサポートする。例：
//TESTCOND IF (RC = 8 | RC = 10) THEN
…
//ELSECOND ELSE
…
//ENDCOND  ENDIF

**JCL記述例**
過去の遺産を継いでいることから、JCL のオペレーション/記述はほかのオペレーティングシステムのジョブ制御よりも複雑である。
下記は、既存のデータセット (IS198.TEST.INPUT) を読んでプログラムABCDEFGHが何か処理を行い、新しくデータセット (IS198.TEST.OUTPUT) を作成してそこに出力するジョブの JCL ステートメントの例である。
//IS198PRS JOB (IS198T30500),'DATA KAKOU',CLASS=L,MSGCLASS=X,NOTIFY=ADM00011
//STEP01   EXEC PGM=ABCDEFGH
//SYSPRINT DD  SYSOUT= //INPUT    DD  DSN=IS198.TEST.INPUT,DISP=SHR
//OUTPUT   DD  DSN=IS198.TEST.OUTPUT,
//           DISP=(NEW,CATLG,DELETE),
//           SPACE=(CYL,(40,5),RLSE),
//           DCB=(RECFM=FB,LRECL=115,BLKSIZE=0),
//           VOL=SER=VOL001
//

**VSE系のJCS**
JCSは、バッチ処理をどのように動かすか、サブシステムをどのように起動させるかを、ジョブエントリーシステム（VSE/POWER）に対して指示するものである。
MVS系と比較すると、JCSの各行の先頭2文字が"//" で始まるのは同じで、機能もほぼ同等だが、各ステートメントの構文はかなり異なる。
なおJCSでは無いが、VSE/POWERに対する指示を行うコマンドはJECL（ジョブ入力制御言語）であり、MVS系のJESコマンドに相当する。

**JOB文**
// JOB jobname
ジョブの先頭に必要。ジョブ名は8文字以内の英数字。

**EXEC PGM文**
// EXEC progname,SIZE=nn,PARM=parm
プログラムの実行。プログラムが必要な記憶域やパラメータを指定できる。

**EXEC PROC文**
// EXEC progname,SIZE=,PARM=parm
プロシージャー（一連のJCSを事前登録したもの）の実行。

**ASSIGN文**
// ASSIGN devicename,address
入出力装置の指定。プログラム内の論理装置名と、物理装置のアドレスを関連づける。

**DLBL/EXTENT文**
// DLBL file-name,'file-id'
および
// EXTENT device-name,volser,,,start-address,capacity
磁気ディスク装置上のファイルの関連づけ。順次ファイルの場合のみEXTENTも必要。

**LIBDEF文**
// LIBDEF type,SEARCH=librarylost
VSEのライブラリーを指定。

**TLBL文**
// TLBL file-name,file-id,date,file-serial-no,volume-sequence-no,file-sequence-no
標準ラベル(Standard Label、SL)付きの磁気テープ使用時に指定。

**UPSI文**
// UPSI xxxxxxxx
CPUの外部スイッチ・シミュレーション。

**OPTION文**
// OPTION
コンパイラーに対する出力形態の指示。

**IF-GOTO文**
// IF $RC または $MRC ...
// GOTO label
ステップの戻りコード検査および制御。実行されたステップの戻りコードに応じて、後続のステップをスキップするなどができる。MVS系の COND パラメータに相当。

**終了文**
/&
ジョブの終わりであることを示す。

**JCS記述例**
//JOB   JOB12345
//ASSGN SYS005,241
//ASSGN SYS010,DISK,VOL=VOL555
//DLBL FILEA,'SAMPLE.FILE'
//EXTENT
//EXEC PROGA,SIZE=xxx,PARM=ABCDE

**XSPのJCL**

**JCL記述例**
\         JOB　JOB1234,ACCT='USER001',PRTY=(1,1),LIST=A 
\STEP0001 EX　PROG1234,COND=10 
\         FD PRGLIB=DA,FILE=SYSPRG 
\         FD CF=DA,FILE=TEST.FILEA 
\         FD SYSDBOUT=DA,VOL=VOL1,TRK=(2,1,RLSE),SOUT=A

**GCOSのJCL**

**JCL記述例**
例1
$ IDENT 00123,USER-01,DEBUG,TEST
$ OBJECT
.
. Object File
.
$ DKEND
$ EXECUTE ON3,DUMP
$ LIMITS 5,,,5000
*例2
$$j,talk
$$select(ident)
$ program progabc 
$ limit ,24k
$ prmfl **,q,r,netex/adpl.x/exec/testabc 
$ privity

**ACOSのJCL**

**JCL記述例**
ACOS2020(ACOS-6)でコンパイルと実行を行う例
$!JOB! ;A, U,,,, JPA4
$!SX
$!FRT77!SOURCE
read(5, 10) i, j
10 format(2i2)
k=i+j
I= i-j
write(6,20)i,j,k, I
20 format(lh ,4i10)
stop
end
$!GO
8 4
$!ENDJOB

**脚注**

**関連項目**
メインフレーム
*MVS
**OS/360
**Multiple Virtual Storage
**データセット (IBMメインフレーム)
**IBM メインフレーム ユーティリティプログラム（JCL記述例あり）
*VSE
**z/VSE
*GCOS
**GCOS
**ACOS

**外部リンク**
 MVS関連（MVS、OS/390、z/OS）
**date=20040219070956（JCL簡易解説あり）
** サンプルJCL集
** z/OS MVS JCLユーザーズガイド
** z/OS MVS JCL Reference（英文。z/OS各バージョン）- VSE関連
**  z/VSE V4R1.1 System Control Statements マニュアル（英文）
** IBM - z/VSEマニュアル（英文）- MSP/XSP関連
**  ジョブフロー作成ツール「ＪＥＴ-Ｗｉｎ」の富士通MSP/XSPのJCLサンプル- GCOS関連
**  GCOS 8 JCL Reference Manual（英文）
**  AN INTRODUCTION TO GCOS BATCH PROCESSING（英文）- その他
**  JCL & Mainframe related Discussion group