あらゆるエンタープライズ・メインフレームは、現代の開発者のほとんどが書いたことのない、密接に絡み合った2つの言語で動作しています。COBOLは、ビジネスロジック、計算、ファイル処理、レコード変換、規制報告などを実装します。JCL(ジョブ制御言語)は、そのロジックの実行を統括し、どのプログラムが、どの順序で、どのファイルを使って、どのような条件下で、成功または失敗した場合に何が起こるかを定義します。どちらの言語も、もう一方の言語なしでは成り立ちません。COBOLプログラムは、入力ファイルがどこから来るのか、出力がどこに行くのかを知りませんが、JCLは最初のレコードが読み込まれる前に、これらの疑問に答えます。
メインフレームシステムの保守、監査、または近代化を行う組織にとって、JCLとCOBOLの関係を理解することは、必須の知識です。あらゆる変更前の影響分析、移行前のドキュメント作成、専門家の退職前の知識移転など、すべてにおいて必要不可欠な前提条件となります。夜間請求処理を行うジョブ、四半期ごとの規制報告書を作成するバッチ処理、あるシステムから別のシステムにデータを供給するプロシージャなど、これらはすべてJCLで定義され、COBOLで実行され、両方を扱った経験のあるエンジニアはごく少数しかいません。
JCLとは何ですか?
JCLはジョブ制御言語の略です。IBMメインフレームシステムでバッチジョブを実行するために使用されるスクリプト言語です。JCL自体はデータを処理しません。どのプログラムを実行するか、どのファイルを利用可能にするか、どのメモリとCPUリソースを割り当てるか、ステップが失敗した場合の処理、単一ジョブ内の複数のステップをどのような順序で実行するかなど、プログラムの実行方法をオペレーティングシステムに指示します。
すべてのJCLジョブは、3つの基本的なステートメントタイプで構成されています。
JOBステートメントは、システムにジョブを識別させ、会計、優先順位、およびスケジューリングのパラメータを定義します。
EXEC文は、ステップ内で実行するプログラムまたはプロシージャを指定します。
DD(データ定義)ステートメントは、プログラムが読み書きするデータセットを、その場所、形式、および処理方法を含めて定義します。
JCL
//PAYBATCH JOB (ACCT#7), 'PAYROLL RUN',
// CLASS=A, MSGCLASS=X, NOTIFY=&SYSUID
//*
//STEP010 EXEC PGM=PAYROLL1
//STEPLIB DD DSN=PROD.PAYROLL.LOADLIB,DISP=SHR
//EMPFILE DD DSN=PROD.PAYROLL.EMPLOYEE,DISP=SHR
//TRANSACT DD DSN=PROD.PAYROLL.TRANS.D&&DATE,DISP=SHR
//PAYRPT DD SYSOUT=A
//SYSOUT DD SYSOUT=*
//SYSIN DD DUMMY
この例では: PAYBATCH ジョブ名です。 STEP010 これは仕事のステップの1つです。 PGM=PAYROLL1 COBOL プログラムの名前を指定し、DD ステートメントはプログラムがアクセスできるすべてのファイルを定義します。 PAYROLL1 知らないし、気にもしない EMPFILE or TRANSACT 物理的な場所から取得されたデータは、DD名で読み取られます。JCLは実行開始前に、物理的な場所、レコード形式、およびアクセスモードを解決します。
JCLカタログ登録済みプロシージャ(PROC)
メインフレームチームは、すべてのジョブに対して同じJCLパターンを作成するのではなく、再利用可能な実行パターンをカプセル化したカタログプロシージャ(PROC)を定義します。PROCはプロシージャライブラリに格納されるテンプレートであり、個々のジョブはそれを参照し、必要に応じて特定のパラメータを上書きします。
JCL
//PAYPROC PROC RUNDATE=TODAY
//COMPILE EXEC PGM=IGYCRCTL,PARM='OBJECT,NODUMP'
//SYSIN DD DSN=PROD.COBOL.SRC(&MEMBER),DISP=SHR
//SYSOBJ DD DSN=&&OBJSET,DISP=(NEW,PASS),
// UNIT=SYSDA,SPACE=(TRK,(10,5))
//LKED EXEC PGM=IEWL,PARM='LIST,LET,XREF'
//SYSLIN DD DSN=&&OBJSET,DISP=(OLD,DELETE)
//SYSLMOD DD DSN=PROD.PAYROLL.LOADLIB(&MEMBER),
// DISP=SHR
// PEND
ジョブからPROCを呼び出す:
JCL
//COMPILE EXEC PAYPROC,MEMBER=PAYROLL1,RUNDATE=20251205
この単一の EXEC ステートメントは、実行時に完全な PROC に展開され、 MEMBER (NAIST) と RUNDATE どこでも置き換えられる &MEMBER (NAIST) と &RUNDATE PROC は、JCL から COBOL へのマッピングが複雑になる主な理由の 1 つは、ジョブが単一の PROC 参照を介して数十個の COBOL プログラムを呼び出す可能性があり、実際に呼び出されるプログラムは実行ごとに変化するシンボル パラメータに依存します。
JCLとCOBOLの違いは何ですか?
JCLとCOBOLはしばしば一緒に語られますが、それぞれ全く異なる役割を担っています。どちらかが他方を置き換えることはなく、メインフレームのバッチ処理を機能させるには両方とも必要です。
| 次元 | JCL | COBOL |
|---|---|---|
| 目的 | 実行を統括する | ビジネスロジックを実装する |
| それが定義するもの | ジョブ、ステップ、ファイル、条件 | プログラム、データ構造、計算 |
| 実行時 | プログラム実行前(セットアップ)と実行後(クリーンアップ) | プログラム実行中 |
| データの読み書き | データセット割り当て(DDステートメント)による | ファイルセクションとREAD/WRITEステートメントを介して |
| エラー処理 | 戻りコード、条件付きステップ実行 | 例外ハンドラ、エラールーチンの実行 |
| 携帯性 | IBM z/OS固有 | コンパイラによりプラットフォーム間で移植可能 |
| 誰が書いたのか | システムプログラマー、バッチエンジニア | アプリケーション開発者 |
| 現代の同等品 | CI/CDパイプライン+コンテナオーケストレーション | アプリケーションコード(Java、Python、C++) |
この関係性を最も簡単に理解する方法は、JCLがデプロイメントおよびオーケストレーション層、COBOLがアプリケーション層であると考えることです。最新のクラウドネイティブシステムでは、JCLの役割はKubernetesジョブマニフェスト、シェルスクリプト、CI/CDパイプラインステージによって担われ、COBOLの役割はJava、Python、またはGoで記述されたアプリケーションサービスによって担われます。
JCLがCOBOLを呼び出す方法:実行チェーン
JCLジョブからCOBOL実行までの経路は、一貫した流れをたどります。各ステップを理解することが、JCLからCOBOLへのマッピングで何を捉えるべきかを理解するための基礎となります。
ステップ1:ジョブの投入。JCLジョブはジョブ入力サブシステム(JES)に投入されます。JESはジョブをキューに入れ、そのステートメントの読み取りを開始します。
ステップ2:ステップ設定。各EXECステップにおいて、システムはSTEPLIB DDステートメントで指定されたロードライブラリから指定されたプログラムを検索します。STEPLIBが指定されていない場合は、システムはシステムリンクライブラリを検索します。
ステップ3:データセットの割り当て。プログラムの実行前に、システムはステップ内のDDステートメントで定義されたすべてのデータセットを割り当てます。これには、ファイルのオープン、入力データセットの存在確認、および出力データセットの作成が含まれます。
ステップ4:プログラムの実行。 COBOLプログラムが実行されます。JCLで定義されたddnameを使用してファイルにアクセスします。 OPEN INPUT EMPFILE COBOLでは、DDステートメントに直接マッピングされます。 EMPFILE JCLにおいて。
ステップ5:戻りコードの評価。 COBOLプログラムが終了すると、リターンコードが設定されます(通常、成功の場合は0、警告の場合は4、エラーの場合は8、重大なエラーの場合は12または16)。JCLはこれを使用します COND パラメータまたは IF/THEN/ELSE このコードに基づいて、後続のステップを実行するかどうかを判断するための構成要素。
ステップ6:データセットの処理。このステップの後、システムは各DDステートメントで定義されたデータセットの処理(保持、削除、カタログ化、カタログ解除、または次のステップへの実行)を実行します。
次の例は、この処理チェーンが実際にどのように見えるかを示しています。左側がJCL、右側がそれに対応するCOBOL要素です。
JCL
//STEP020 EXEC PGM=ACCTREC
//STEPLIB DD DSN=PROD.ACCOUNT.LOADLIB,DISP=SHR
//INFILE DD DSN=PROD.ACCT.DAILY.INPUT,DISP=SHR ← maps to COBOL SELECT/ASSIGN
//OUTFILE DD DSN=PROD.ACCT.PROCESSED, ← maps to COBOL SELECT/ASSIGN
// DISP=(NEW,CATLG,DELETE),
// UNIT=SYSDA,SPACE=(CYL,(5,2),RLSE)
//RPTFILE DD SYSOUT=A ← maps to COBOL WRITE report
//SYSOUT DD SYSOUT=*
COBOLプログラム ACCTREC 含まれています。
COBOL
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT INFILE ASSIGN TO INFILE. *> maps to DD INFILE
SELECT OUTFILE ASSIGN TO OUTFILE. *> maps to DD OUTFILE
SELECT RPTFILE ASSIGN TO RPTFILE. *> maps to DD RPTFILE
DATA DIVISION.
FILE SECTION.
FD INFILE
RECORDING MODE IS F
BLOCK CONTAINS 0 RECORDS
RECORD CONTAINS 200 CHARACTERS.
01 ACCOUNT-RECORD.
05 ACCT-NUMBER PIC X(10).
05 ACCT-BALANCE PIC S9(13)V99 COMP-3.
05 ACCT-STATUS PIC X(2).
その SELECT INFILE ASSIGN TO INFILE COBOLのFILE-CONTROLセクションは、DDステートメントに接続します。 INFILE JCLでは、これが基本的なマッピング関係です。COBOLは論理ファイル名を使用し、JCLはそれらを物理データセットに解決します。
JCLの異常終了コード:その意味
JCL アベンド コード (異常終了コード) は、ジョブ ステップが予期せず終了した理由を示します。ジョブ出力には次のように表示されます。 S000 (システム異常終了)または U0000 (ユーザー異常終了)コード。バッチジョブの失敗を診断するには、これらのコードを理解することが不可欠です。
| 異常終了コード | タイプ | 一般的な原因 |
|---|---|---|
| S001 | システム | データセットの読み取りまたは書き込み中にI/Oエラーが発生しました |
| S013 | システム | JCL DDとCOBOL FD間のDCB属性の不一致、レコード長の不一致、またはフォーマットの不一致 |
| S0C4 | システム | ストレージ保護例外が発生しました。プログラムが割り当てられた領域外のメモリにアクセスしようとしました。 |
| S0C7 | システム | データ例外、非数値データに対する算術演算の試行(COBOLで非常によく発生する異常終了) |
| S322 | システム | 時間制限を超過しました。ジョブの実行時間がTIMEパラメータで許可された時間を超えました。 |
| S806 | システム | ロードモジュールが見つかりません。EXEC PGM= で指定されたプログラムは、検索されたロードライブラリに存在しません。 |
| S913 | システム | データセットへのアクセスセキュリティ違反、RACFまたは同等のアクセス拒否 |
| U0000 | ユーザー | アプリケーション定義の異常終了、COBOLプログラムがユーザーコードを使用してSTOP RUNを呼び出しました |
| U4076 | ユーザー | IMS固有の異常終了、データベースアクセス失敗 |
最も一般的な生産異常終了、 S0C7これは、COBOLプログラムがスペースや非数値文字を含むフィールドに対して算術演算を実行しようとしたときに発生します。典型的な原因は、COBOLプログラムで想定されるデータ形式とJCLによって実際に提供されるデータ形式との不一致です。これはまさに、JCL-to-COBOLマッピングによって、深夜の運用障害が発生する前に明らかになる種類の不一致です。
CONDパラメータと条件付き実行
JCL は、前のステップからの戻りコードに基づいてどのステップを実行するかを制御します。 COND パラメータ を使用します。
JCL
//STEP010 EXEC PGM=VALIDATE,COND=(4,LT)
//STEP020 EXEC PGM=PROCESS, COND=(4,LT,STEP010)
//STEP030 EXEC PGM=CLEANUP, COND=(0,NE,STEP010)
COND=(4,LT) つまり、前のステップの戻りコードが4未満の場合、このステップをスキップします。 COND=(4,LT,STEP010) つまり、STEP010の戻りコードが4未満の場合は、このステップをスキップします。 COND=(0,NE,STEP010) つまり、STEP010の戻りコードが0でない場合はSTEP030をスキップし、STEP010が成功した場合にのみクリーンアップを実行します。
現代の JCL は IF/THEN/ELSE/ENDIF 代わりに、より読みやすいように以下のように記述します。
JCL
//IF010 IF (STEP010.RC = 0) THEN
//STEP020 EXEC PGM=PROCESS
// ENDIF
//IF020 IF (STEP010.RC > 4) THEN
//STEP030 EXEC PGM=ERRORHANDLER
// ENDIF
条件付き実行パスのマッピングは、JCLからCOBOLへの分析において最も重要でありながら、最も見落とされがちな要素の一つです。前のステップが失敗した場合にのみ実行されるCOBOLプログラムは、エラー条件、ロールバックロジック、またはリカバリ手順を処理している可能性があります。これらの機能は、それを制御するJCLを考慮せずにCOBOLソースだけを見ても、全く見えません。
JCL、COBOL、およびDB2:3層スタック
ほとんどのメインフレームトランザクションシステムでは、JCLとCOBOLに加えて、IBMのリレーショナルデータベースであるDB2という第3のコンポーネントが使用されます。COBOLプログラムは、埋め込みSQL文(EXEC SQLブロック)を介してDB2にアクセスします。JCLは、特定のDD文を介してDB2サブシステム接続とDBRM(データベース要求モジュール)を管理します。
JCL
//DBRM DD DSN=PROD.DBRMLIB.DATA(ACCTREC),DISP=SHR
//SYSPRINT DD SYSOUT=*
COBOL
WORKING-STORAGE SECTION.
EXEC SQL
INCLUDE SQLCA
END-EXEC.
PROCEDURE DIVISION.
MAIN-LOGIC.
EXEC SQL
SELECT ACCT_BALANCE, ACCT_STATUS
INTO :WS-BALANCE, :WS-STATUS
FROM ACCOUNT_MASTER
WHERE ACCT_NUMBER = :WS-ACCT-NUM
END-EXEC.
IF SQLCODE NOT = 0
PERFORM DB2-ERROR-ROUTINE
END-IF.
JCL-COBOL-DB2スタックでは、JCLが実行環境とデータセットへのアクセスを提供し、COBOLがビジネスロジックを実装してデータベースを呼び出し、DB2がCOBOLプログラムに埋め込まれたSQLに従ってデータを格納および取得します。DB2を使用するCOBOLプログラムの完全な依存関係マップには、どのJCLジョブがそのプログラムを呼び出すかだけでなく、どのDB2テーブルを読み書きするか、どの列にアクセスするか、そしてどの他のプログラムが同じテーブルにアクセスするかを含める必要があります。なぜなら、テーブルのスキーマ変更は、そのテーブルを参照するすべてのCOBOLプログラムに影響を与えるからです。
JCLからCOBOLへのマッピングが近代化にとって重要な理由
JCLをCOBOLにマッピングすることは、主に技術的な作業ではありません。リスク管理の作業です。JCLパラメータの変更、ステップの追加、データセット名の変更、ジョブが呼び出すCOBOLプログラムの変更など、メインフレームシステムへのあらゆる変更は、変更されたコンポーネントにとどまらず、広範囲に影響を及ぼします。変更を行う前に、これらの影響範囲を正確に把握する唯一の方法は、既存のシステムとそれらがどのように接続されているかを完全に把握することです。
移行前:バッチワークロードをメインフレームからクラウドに移行するには、どのJCLジョブが存在するか、それらがどのCOBOLプログラムを呼び出すか、どのデータセットがステップ間でやり取りされるか、実行順序はどうなっているか、ステップが失敗した場合に何が起こるかを把握しておく必要があります。このマップがなければ、移行チームは不完全なドキュメント、あるいはドキュメントがまったくない状態で作業することになります。その結果、ステップが漏れたり、依存関係が本番環境で発見されたり、切り替え日が遅れたりする可能性があります。
コード変更を行う前に:どのJCLジョブがCOBOLプログラムを呼び出すかを確認せずにCOBOLプログラムを変更すると、異なる条件下や異なるデータセット構成で実行されるジョブが動作しなくなる可能性があります。ローカルな変更に見えるJCLパラメータの変更でも、特定のデータセット属性に依存するCOBOLプログラムの動作に影響を与える可能性があります。影響分析を行うには、変更を行う前にJCLからCOBOL、そしてデータセットに至る完全な連鎖を把握しておく必要があります。
知識の継承について:バッチシステムを20年間保守してきたCOBOL開発者が退職する際、JCLジョブとCOBOLプログラムがどのように連携するかという概念モデルも一緒に持ち去ってしまいます。文書化されたマップこそが、その知識を次のチームに継承する唯一の手段です。それがなければ、新しい開発者は安全に修正できないシステムを引き継ぐことになります。
コンプライアンス監査の場合:規制監査では、財務計算、データ変換、アクセス制御が文書化されたとおりに動作していることを証明する必要がある場合がよくあります。JCLとCOBOLの関係が文書化されていない場合、監査の圧力下でシステムをリバースエンジニアリングしない限り、これを証明することは不可能です。
JCL管理ツールおよび分析プラットフォーム
この記事の検索コンソールのデータが多言語対応であること(イタリア語、フランス語、スペイン語、日本語、ドイツ語でJCL管理ツールに関するクエリが含まれている)は、メインフレームITコミュニティがいかにグローバルに分散しているか、そしてあらゆる地域のチームがいかに一貫して同じ問題に直面しているかを反映している。つまり、JCLとCOBOLのドキュメントが不完全、古くなっている、あるいは存在しないということだ。
JCLの分析と管理に利用できるツールは、以下の3つのカテゴリに分類されます。
IBMネイティブツール:IBMは、ジョブ入力サブシステム機能、JESスプール管理、およびIBM z/OSバッチランタイムを提供しています。これらは実行と監視を処理しますが、プログラム間の依存関係分析や視覚化機能は提供しません。
サードパーティ製のジョブスケジューラ(CA7、TWS(Tivoli Workload Scheduler)、BroadcomのESP Workload Automationなど)は、数千ものジョブにわたるバッチスケジューリングを管理し、依存関係に基づいたスケジューリングを提供し、障害発生時にはアラートを発信します。これらのスケジューラはジョブレベルの依存関係を理解しますが、通常は各ステップ内で呼び出されるCOBOLプログラムを分析しません。
静的コード解析および依存関係マッピングプラットフォーム:JCLおよびCOBOLソースコードを解析し、どのジョブがどのプログラムを呼び出すか、どのプログラムがどのデータセットにアクセスするか、そしてシステム全体でデータがどのように流れるかといった構造モデルを構築するツールです。これらのツールは、ジョブスケジューラやIBMネイティブツールでは不可能な、レイヤー間の可視性を提供します。例えば、特定のJCL DDステートメントとそれにマッピングされるCOBOL FILE-CONTROLエントリとの関係、あるいはデータセットに書き込むCOBOLプログラムと、そのデータセットを入力として読み込む次のジョブとの関係などが把握できます。
SMART TS XL このツールは、この第3のカテゴリに属し、COBOL、JCL、PL/I、アセンブラ、SQL、Javaなど、企業環境におけるあらゆる言語を網羅するように拡張されており、単一言語ツールでは実現できない言語横断的な構造分析を提供します。
認定条件 SMART TS XL エンタープライズ規模でJCLをCOBOLにマッピングします
JCLからCOBOLへの手動マッピングは、3ステップの単一ジョブであれば処理可能です。しかし、5万個のJCLジョブ、20万個のCOBOLプログラム、そして40年以上にわたって蓄積された数百万件のデータセット参照を抱える組織では、処理は不可能です。特定のプロシージャ、そのプロシージャを呼び出すために使用されるシンボルパラメータ、それらのパラメータが解決されるCOBOLプログラム、そしてそれらのプログラムがアクセスするデータセット間の関係を、この規模で手作業で追跡することは不可能です。
SMART TS XL JCLおよびCOBOLのソースコード(シンボルパラメータ置換を含むPROC、インストリームプロシージャ、INCLUDEメンバー、オーバーライド、条件付き実行ロジックなど)を解析し、システム内のすべての構造的関係を表す統合された相互参照モデルを構築します。このモデルは、手動で更新されるドキュメントとして維持されるのではなく、ソースから再生成されるため、クエリ可能でナビゲーションが可能であり、常に最新の状態に保たれます。
その JCLの拡張 この機能は、シンボルパラメータ置換を解決して、呼び出し元のジョブごとに適用されるオーバーライドを考慮しながら、任意の PROC によって呼び出される実際のプログラムとデータセットを表示します。 &PGMNAME シンボルパラメータは、未解決の参照としてではなく、すべての呼び出し元で解決されるすべての具体的なプログラムとしてモデルに現れます。
アプリケーション依存関係マッピング機能は、JCLジョブからCOBOLプログラム、DB2テーブル、そしてダウンストリームプログラムに至るまで、システム内のすべてのコンポーネントとそれらの間のすべての接続を示す完全なグラフを構築します。近代化変更を行う前に、チームは次のようなクエリを実行できます。どのジョブがこのプログラムを呼び出すのか?このプログラムはどのデータセットを読み取るのか?他のどのプログラムがそれらのデータセットに書き込むのか?シーケンスの次のジョブはどれか?
影響分析機能は、提案された変更に対して、列挙された影響範囲を生成します。たとえば、このコピーブックを変更すると、それを含むすべてのプログラムが表示されます。このデータセットのレイアウトを変更すると、それを参照するすべての JCL DD ステートメントが表示されます。ジョブからこのステップを削除すると、その出力に依存するすべての下流ステップが表示されます。
JCLからCOBOLへのマッピングに取り組むチームにとって レガシーの近代化 プログラム、 SMART TS XL これは、アスタディア、TSRI、アドバンストなどの近代化ベンダーが変換作業を開始する前に必要とする基盤、つまり、既存の構造に関する完全かつ正確なインベントリを提供し、変換範囲を仮定ではなく分析に基づいて定義できるようにするものです。
地図は領土そのものではなく、出発点である。
JCLとCOBOLは今後も使われ続けるだろう。給与計算、保険金請求処理、規制報告書の作成、金融取引の決済といったバッチ処理システムは、クラウド移行の計画、承認、資金調達、実行が行われる間、メインフレーム上で稼働し続ける。クラウド移行は通常、数ヶ月ではなく数年を要するプロセスだ。その間、システムの保守、修正、理解は不可欠となる。
JCLからCOBOLへのマッピングは、一度きりのプロジェクトではありません。プログラムの変更、ジョブの追加、データセットの再編成などに応じて構造モデルを常に最新の状態に保つ、継続的な取り組みです。この取り組みに投資するチームは、業界のほとんどがブラックボックスとして扱うシステムに対しても、自信を持って変更を加えることができます。そうでないチームは、システムを完全に把握できないまま変更を加えており、依存関係の欠落がコンパイラエラーにはならないものの、深夜3時のバッチ処理中に本番環境で障害が発生するような状況に陥っています。


