작업 제어 언어

작업 제어 언어(, JCL)는 IBM 메인프레임 운영 체제에 사용되는 스크립트 언어로, 일괄 처리 작업을 수행하거나 하부 시스템을 시작하는 방법을 시스템에 지시한다.
실제로 IBM JCL에는 두 가지가 있다: 하나는 DOS/360으로 시작하는 운영 체제 계열에 대한 것(최신의 것이 z/VSE). 나머지 하나는 OS/360부터 z/OS에 이르는 계열에 대한 것. 이들은 몇 가지 기본적인 문법과 몇 가지 기본 개념은 동일하지만 그 밖의 것들은 매우 다르다.
도스 및 OS JCL에 공통적으로 쓰이는 기능.
잡, 스텝, 프로시저.
도스 JCL과 OS JCL에서 일의 단위는 잡(job)이다. 하나의 잡은 하나 이상의 스텝(step)을 이루며, 각 스텝은 하나의 특정 프로그램을 실행하기 위한 요청이다.
이를테면 관계형 데이터베이스 시대 이전에, 관리를 위한 인쇄물 형태의 보고서를 만들어내는 잡은 다음의 스텝들을 이룰 수 있다:
도스 JCL, OS JCL 둘 다 최초의 카드(card)는 JOB 카드여야 한다. 이 카드는 다음을 수행한다.
프로시저(proc)는 잡에 삽입된, 스텝 및 스텝 그룹에 대해 미리 작성된 JCL이다. 도스 JCL과 OS JCL 둘 다 이러한 프로시저를 사용할 수 있다. 프로시저는 하나의 잡이나 각기 다른 잡에서 여러 번 사용되는 스텝을 되풀이하는데 쓰인다. 이를 통해 프로그래머의 시간을 절약하고 오류의 위험도를 낮출 수 있다. 프로시저를 실행하기 위해 JCL 파일에 하나의 카드를 포함할 수 있는데, 이 카드는 프로시저를 특정한 파일로부터 복사한 뒤 이를 작업 흐름에 삽입한다. 또, 프로시저는 매개변수(parameter)를 포함하여 개별 이용에 맞게 프로시저를 맞춤식으로 정의할 수 있다.
기본 문법.
도스, OS JCL 둘 다 한 줄에 이용 가능한 길이는 최대 80자인데, 그 까닭은 DOS/360, OS/360이 처음 사용되었을 때 새로운 입력을 컴퓨터 시스템에 제공한 주 방식이 80열 천공 카드였기 때문이다. 나중에 더 길어진 레코드 길이로 디스크나 테이프 파일을 통해 잡을 제출할 수 있게 되었지만 운영 체제의 잡 제출 구성 요소들은 80자가 넘어가는 문자들은 모두 무시했다.
더 구체적으로 말해 두 운영 체제 계열은 한 줄에 단지 71자만 사용한다. 73번째부터 80번째까지의 글자들은 일반적으로 카드 시퀀스 번호이며, 운영 체제가 보고하는 오류의 위치를 찾아내는데 유용하다. 72번째 문자는 일반적으로 빈 채로 남아 있지만 OS JCL의 경우 비어 있지 않은 문자를 포함함으로써 JCL이 다음 카드에도 계속됨을 지시할 수 있다.
모든 명령어, 매개변수 이름, 값들은 USS 파일 이름을 제외하고는 모두 대문자여야 한다.
인스트림 입력 (아래 참고)을 제외한 모든 줄들은 슬래시 "/"로 시작해야 하며 운영 체제가 처리하는 모든 줄들은 두 개의 슬래시 "//"로 시작해야 한다. (늘 첫 열에서) 그러나 여기에는 두 가지 예외가 있다: 구분문(delimiter statement)과 주석문(comment statement). 구분문은 슬래시와 별표(/*)로 시작하며 주석문은 두 개의 슬래시와 별표(//*)로 시작한다.
수많은 JCL 문은 71자 안에 맞추기에는 너무 길지만 다음의 과정을 통해 연속 카드의 부정수(不定數)로 확장할 수 있다:
가장 일반적인 종류의 카드 구조는 다음과 같다:
인스트림 입력.
도스 JCL과 OS JCL은 둘 다 인스트림 입력을 지원하는데 이를테면 카드들은 운영 체제가 아닌 응용 프로그램이 처리한다. 오랜 기간에 걸쳐 보관해야 하는 데이터는 일반적으로 디스크에 저장되지만, 상호작용적인 터미널이 일반화되기 전까지 이러한 디스크 파일을 만들고 편집하는 유일한 방법은 새로운 데이터를 카드에 공급하는 것이었다.
도스 JCL과 OS JCL은 인스트림 입력의 시작 신호를 주는 방법이 다르지만 둘 다 카드의 첫 열에 인스트림 입력을 "/*"로 마친다는 것은 동일하다.
복잡한 특징들.
유닉스에서의 파일 복사는 다음과 같은 단순한 형태로 가능하다:
 cp oldFile newFile
OS/360 계열에서는 다음과 같다
//IS198CPY JOB (IS198T30500),'COPY JOB',CLASS=L,MSGCLASS=X
//COPY01 EXEC PGM=IEBGENER
//SYSPRINT DD SYSOUT=*
//SYSUT1 DD DSN=OLDFILE,DISP=SHR
//SYSUT2 DD DSN=NEWFILE,
// DISP=(NEW,CATLG,DELETE),
// SPACE=(CYL,(40,5),RLSE),
// DCB=(LRECL=115,BLKSIZE=1150)
//SYSIN DD DUMMY
시스템/360과 PC 환경의 차이는 다음과 같다:
도스 JCL.
위치 매개변수.
// TLBL TAPEFIL,'COPYTAPE.JOB',,2
// ASSGN SYS005,DISK,VOL=VOL01,SHR
// DLBL DISKFIL,'COPYTAPE.JOB',0,SD
// EXTENT SYS005,VOL01,1,0,800,1600
도스 JCL에서 매개변수들은 위치성을 지니므로 읽고 쓰기를 더 어렵게 만든다:
OS JCL 보다 매개변수가 적지만 더 많은 문들을 사용함으로써 도스 JCL은 어느 정도는 위치 매개변수의 난이도를 완화시킨다. ASSGN, DLBL, EXTENT 문들은 OS JCL의 하나의 DD 문과 동일한 일을 한다.
장치 의존성.
초기 DOS/360과 대부분의 DOS/VS 버전에서, 잡을 마칠 때 삭제될 기존의 파일과 임시 파일에 대해서도 개별 디스크나 테이프 파일에 사용될 장치의 모델 번호를 지정해야 했다. 이는 고객이 더 현대적인 형태의 장치로 업그레이드하면 수많은 JCL 파일을 변경해야 함을 뜻한다.
나중에 DOS/360 계열이 등장함에 따라 모델 번호를 요구하는 일이 줄었다.
OS JCL.
이 JCL 언어에 쓰이는 문들은 JCL 문이라 한다. OS JCL은 세 가지 기본 문을 이룬다:
처음부터 OS 계열의 JCL(최대 z/OS를 포함하여)은 더 유연하고 사용하기 더 쉬워졌다.
다음의 예는 1964년 시스템/360이 등장하자마자 제공되는 오래된 스타일의 문법을 사용한다. 이 오래된 문법은 20년 넘도록 여전히 동일하며 약간의 변경 사항만 있을 뿐이다. 이 오래된 잡들은 종종 복잡한데, 이들은 CLIST 문법을 사용하도록 변환하는 일은 다루기 힘들고 시간 소모적이다.
CLIST 문법이 읽기 더 쉬울지라도 프로그래머들은 오래된 문법을 사용하는 것과 동일한 양의 정보를 제공해 주어야 한다.
JCL 문 코딩 규칙.
각 JCL 문은 5개의 필드로 나뉜다.
 Identifier-Field Name-Field Operation-Field Parameter-Field Comments-Field
 no space space space space
식별자 필드(Identifier-Field)는 이름 필드(Name-Field)와 공백 없이 이어져야 한다.
연산 필드는 JOB/EXEC/DD를 말한다.
 JOB - JOB 문
 EXEC - EXEC 문
 DD - DD 문
키워드 매개변수.
//NEWFILE DD DSN=MYFILE01,UNIT=DISK,SPACE=(TRK,80,10),
// DCB=(LRECL=100,BLKSIZE=1000),
// DISP=(NEW,CATLG,DELETE)
OS JCL의 모든 주요 매개변수들은 키워드로 식별되며 어떠한 순서로도 표현이 가능하다. 이 중 일부는 위의 예시처럼 SPACE(새로운 파일에 얼마나 많은 디스크 공간을 할당할 것인지), DCB(파일의 레이아웃의 자세한 사양)와 같은 둘 이상의 하부 매개변수를 포함할 수 있다. 하부 매개변수들은 SPACE에서처럼 가끔 위치성을 띄지만 DCB와 같은 가장 복잡한 매개변수들은 키워드 하부 매개변수가 있다.
위치 매개변수는 키워드 매개변수보다 우선해야 한다. 키워드 매개변수는 등호(=)를 사용하여 언제나 값을 키워드로 할당해야 한다.
장치 독립성.
처음부터 OS 계열 운영 체제의 JCL은 고수준의 장치 독립성을 제공하였다. 잡을 끝낸 뒤 유지되어야 할 새로운 파일들에 대해서도 일반적인 용어(예: UNIT=DISK, UNIT=TAPE)들로 장치 유형을 지정할 수 있다. 물론 문제가 되면 모델 번호라든지, 특정 장치 주소 또한 지정할 수 있다.
매개변수화된 프로시저.
OS JCL 프로시저는 처음부터 매개변수화되었으며 마치 매크로나 단순 함수처럼 만들어준다. 이로써 재사용성을 다양한 환경에서 증대시킨다.
//MYPROC PROC FNAME=MYFILE01,SPTYPE=TRK,SPINIT=50,SPEXT=10,LR=100,BLK=1000
//NEWFILE DD DSN=&amp;FNAME,UNIT=DISK,SPACE=(&amp;SPTYPE,&amp;SPINIT,&amp;SPEXT),
// DCB=(LRECL=&amp;LR,BLKSIZE=&amp;BLK),DISP=(NEW,CATLG,DELETE)
이 예제에서 &amp;로 시작하는 모든 값들은 잡이 프로시저 사용을 요청할 때 지정될 매개변수들이다.
PROC 문은 프로시저에 이름을 줄 뿐만 아니라, 프로그래머가 각각의 매개변수에 대한 기본값을 지정할 수 있게 한다. 그래서 이 예제에서는 하나의 프로세서를 가지고 다양한 크기와 레이아웃의 파일들을 새로 만들어낸다. 이를테면:
//JOB01 JOB ...
//STEP01 EXEC MYPROC FNAME=JOESFILE,SPTYPE=CYL,SPINIT=10,SPEXT=2,LR=100,BLK=2000
또는
//JOB02 JOB ...
//STEP01 EXEC MYPROC FNAME=SUESFILE,SPTYPE=TRK,SPINIT=500,SPEXT=100,LR=100,BLK=5000
오버라이드 기능.
OS는 프로그램들이 포함할 수 있는 파일 구조의 사양 중 일부를 JCL에 오버라이드할 수 있게 한다. 이 기능은 대개 새로운 파일들을 만드는데 사용된다. 이를테면:
//STEP01 EXEC PGM=MYPROG
//NEWFILE DD DSN=MYFILE01,UNIT=DISK,SPACE=(TRK,50,10),DCB=BLKSIZE=1000,
// DISP=(NEW,CATLG,DELETE)
프로그램 MYPROG 내의 코드가 블록 크기를 특정하더라도 새로운 파일이 1000 바이트의 블록 크기를 가질 것이다. 그러므로 프로그램 MYPROG를 변경할 필요가 없다. 한편 이 예제는 DCB의 하부 매개변수 LRECL (레코드 길이)를 지정하지 않고 있으므로 레코드 길이는 MYPROG이 제시하는 바대로 결정된다.
재조회.
멀티 스텝 잡에서 나중의 스텝은 초기 스텝에서 이미 지정한 파일을 통째로 지정하지 않고 재조회를 사용할 수 있다. 이를테면 이 프로시저에서
//MYPROC ...
//MYPR01 EXEC PGM=...
//NEWFILE DD DSN=&amp;MYFILE,UNIT=DISK,SPACE=(TRK,50,10),
// DCB=(LRECL=100,BLKSIZE=1000),DISP=(NEW,CATLG,DELETE)
//MYPR02 EXEC PGM=...
//INPUT01 DD DSN=*.MYPR01.NEWFILE
스텝 MYPR02는 스텝 MYPR01의 NEWFILE로 식별된 파일을 사용한다 (DSN은 데이터셋 이름을 말하며 파일의 이름을 지정한다).
여러 잡에 특화된 JCL과 프로시저 호출이 포함된 잡에서 잡에 특화된 스텝은 프로시저에 온전히 지정된 파일을 재조회할 수 있다. 이를테면:
//MYJOB JOB ...
//STEP01 EXEC MYPROC Using a procedure
//STEP02 EXEC PGM=... Step which is specific to this job
//INPUT01 DD DSN=*.STEP01.MYPR01.NEWFILE
여기서 DSN=*.STEP01.MYPR01.NEWFILE은 "이 잡의 스텝 STEP01이 사용한 프로시저의 스텝 MYPR01의 NEWFILE로 식별된 파일을 사용하라"를 뜻한다. 프로시저의 이름이 아닌 프로시저를 호출한 스텝의 이름을 사용하면 프로그래머가 여러 번 동일한 잡 안에서 재조회에 사용된 프로시저의 인스턴스가 어느 것인지 혼동하지 않고 동일한 프로시저를 사용할 수 있다.
각주.
JCL은 길고 복잡할 수 있어 읽기 쉽지 않다. OS JCL은 프로그래머들이 두 종류의 설명적 주석을 포함할 수 있게 하고 있다:
//MYJOB JOB ...
//* Lines containing only comments.
//******** Often used to divide JCL listing into sections ********
//STEP01 EXEC MYPROC Comment 2 on same line as statement
//STEP02 EXEC PGM=... Comment 3 has been extended and X
// overflows into another line.
//INPUT01 DD DSN=STEP01.MYPR01.NEWFILE
입력 파일들의 연결.
OS JCL은 프로그래머들이 입력 파일들을 하나로 연결시킬 수 있게 하여, 이들이 마치 프로그램을 하나의 파일처럼 보이게 만들어준다. 예를 들어:
 //INPUT01 DD DSN=MYFILE01,DISP=SHR
 // DD DSN=JOESFILE,DISP=SHR
 // DD DSN=SUESFILE,DISP=SHR
2번째, 3번째 문들은 이름 필드에 값이 없으므로 OS는 이들을 "연결"(concatenation)로 취급한다. 파일들은 동일한 기본 형태 (거의 언제나 연속적인)여야 하며 같은 레코드 길이여야 한다.
조건 처리.
OS는 프로그램들이 성공 여부에 대한 반환 코드를 설정할 것이라 예측한다. 가장 일반적이고 전통적인 값들은 다음과 같다:
OS JCL은 반환 코드를 COND (조건 코드)로 지시하며, 이를 이용하여 차기 단계들의 실행 여부를 결정한다.
//MYJOB JOB ...
//STEP01 EXEC PGM=PROG01
//STEP02 EXEC PGM=PROG02,COND=(4,GT,STEP01)
//STEP03 EXEC PGM=PROG03,COND=(8,LE)
//STEP04 EXEC PGM=PROG04,COND=(ONLY,STEP01)
//STEP05 EXEC PGM=PROG05,COND=(EVEN,STEP03)
상기의 예는 아래의 의사코드로 변환할 수 있다:
 run STEP01
 if STEP01's return code is greater than or equal to 4 then
 run STEP02
 end if
 if any previous return code is less than 8 then
 run STEP03
 end if
 if STEP01 abnormally ended then
 run STEP04
 end if
 if STEP03 abnormally ended then
 run STEP05
 else
 run STEP05
 end if
뒤에 COND 문이 있는 스텝을 읽음으로써 이들을 매우 쉽게 이해할 수 있다. 그러나 나중에 IBM은 COND 매개변수를 보유하면서도 IF 조건문을 JCL에 도입하여 프로그래머들이 코딩을 쉽게 할 수 있게 해 주었다. (COND 변수를 사용하는 기존의 JCL에 대한 변경을 방지)
JCL 유틸리티.
JCL은 수많은 IBM 유틸리티 프로그램을 사용하여 데이터 처리를 돕는다. 유틸리티들은 일괄 처리에 가장 유용하다. 이 유틸리티들은 세 개의 집합을 이룬다:
작업 엔트리 제어 언어.
IBM 메인프레임 시스템에서 작업 엔트리 제어 언어(Job Entry Control Language, JECL)는 z/VSE용 z/OS나 VSE/POWER에서 스풀링 서브시스템 JES2 또는 JES3용 정보를 제공하는 명령 언어 제어문들믜 모임이다. JECL 문들은 네트워크 컴퓨터가 작업을 실행할지, 작업을 언제 실행할지, 결과 출력물을 어디로 보낼지 지정할 수 있다.
JECL은 운영 체제에게 어떻게 작업을 실행하는지를 지시하는 작업 제어 언어와는 구별된다.