📋 JCL — década de 1960

⬅️ Atlas · 🧟 Lenguajes que siguen vivos · 📚 Índice de clases

No es un lenguaje de programación, y por eso hay que estudiarlo. JCL no calcula nada: describe qué programa ejecutar, con qué datos y en qué orden. Todo el proceso nocturno por lotes de la banca mundial —el momento en que se liquidan las operaciones del día— está descrito en JCL.

🎯 Por qué está en este programa

Criterio de inclusión: JCL se ejecuta cada noche en cada mainframe z/OS del planeta. Es la pieza sin la cual el COBOL y el PL/I de producción no arrancan. Quien trabaje profesionalmente con mainframe escribe JCL a diario, aunque no escriba COBOL.

Y entra, sobre todo, porque enseña una separación que los lenguajes del núcleo tienen borrosa: la que hay entre el programa y su entorno de ejecución. Un programa COBOL no sabe dónde están sus ficheros: se refiere a nombres lógicos (ddnames), y es el JCL quien los conecta a ficheros reales en el momento de ejecutar. Eso es inyección de dependencias a nivel de sistema operativo, en 1964. La misma idea que hoy llamamos "configuración por entorno", "volúmenes de Docker" o "los doce factores" estaba resuelta —de otra manera y con otro vocabulario— antes de que existiera Unix. Y su COND sobre códigos de retorno es el antepasado directo de cualquier pipeline de CI que decide si el siguiente paso se ejecuta.

Año 1964, con el IBM System/360 y el sistema operativo OS/360
Autoría IBM
Familia Lenguajes de control de trabajos (job control)
Paradigma Declarativo: describe recursos y secuencia, no algoritmos
Tipado No aplica — describe recursos, no valores
Memoria No aplica; sí gestiona asignación de espacio en disco
Ejecución Interpretado por el subsistema de entrada de trabajos (JES2/JES3) de z/OS
Estado 🟢 Imprescindible en el mundo mainframe — banca, seguros, gobierno, retail

📜 Historia

Cuando IBM lanzó el System/360 en 1964, resolvió un problema que hoy ni nos planteamos: cómo decirle a un ordenador compartido qué hacer a continuación. No había línea de comandos, ni sesión interactiva, ni terminal. Se entregaba una bandeja de tarjetas perforadas al operador, y esa bandeja tenía que explicarse a sí misma: qué programa cargar, cuánta memoria necesitaba, en qué unidad de cinta estaba la entrada, dónde dejar la salida, cuánto podía tardar y qué hacer si fallaba.

JCL es ese lenguaje de descripción. Sus rarezas se explican todas por la tarjeta perforada:

Sesenta años después, esas columnas siguen siendo obligatorias.

El modelo conceptual es de tres niveles, y no ha cambiado:

🏭 Dónde sobrevive hoy

🧠 Por qué no ha muerto

1. Porque el proceso por lotes no ha muerto. Hay trabajo que solo tiene sentido hacer en bloque a una hora fija: cerrar un día contable, calcular intereses sobre todas las cuentas, compensar entre bancos. Eso no es un microservicio, es un lote, y necesita alguien que lo describa.

2. El desacoplamiento programa/datos es real y sigue siendo útil. El programa dice SELECT CLIENTES ASSIGN TO ENTRADA; el JCL dice //ENTRADA DD DSN=PROD.CLIENTES.2026,DISP=SHR. Cambiar de fichero de prueba a fichero de producción no toca ni una línea del programa ni requiere recompilar. Es exactamente el problema que resuelven hoy las variables de entorno y los volúmenes montados.

3. La gestión de recursos es explícita y auditable. El JCL declara cuánto espacio pedir, en qué volumen, con qué disposición si el trabajo falla, y qué hacer con el fichero después. En un sistema compartido por miles de trabajos con SLA, esa explicitud es una característica, no una molestia.

4. Los códigos de retorno gobiernan el flujo. COND —y su forma moderna IF/THEN/ELSE— decide si un paso se ejecuta según cómo terminaron los anteriores. Es el mismo modelo mental que && en un shell o needs: en GitHub Actions.

5. Décadas de mallas de trabajos con dependencias. Rehacerlo implica reconstruir el mapa completo de qué depende de qué, y ese mapa muchas veces solo existe en la propia malla.

🔄 Lo que se ha modernizado

⚙️ Cómo se ejecuta hoy

# Desde ISPF/TSO en el propio mainframe: se edita el JCL y se teclea
SUBMIT

# Desde fuera, con Zowe CLI — así es como se hace hoy desde un portátil:
zowe jobs submit local-file "./totvta.jcl" --view-all-spool-content
zowe jobs list jobs --owner VLAD

Para aprender sin acceso a un mainframe: IBM Z Xplore ofrece un entorno gratuito con ejercicios guiados; el emulador Hercules con MVS 3.8j (de dominio público) permite montar un mainframe de los 70 en un portátil, con su JCL auténtico.

🧪 El programa de la clase 041… en JCL

⚠️ Aquí el contrato cambia de naturaleza, y es justo el punto. JCL no puede calcular el total de una venta: no tiene variables, ni aritmética, ni expresiones. Lo que hace es compilar el programa COBOL de la clase 041, ejecutarlo, darle la entrada y recoger la salida. Fingir un JCL que multiplica números sería inventar un lenguaje que no existe. No se verifica en CI: requiere z/OS.

//TOTVTA   JOB (CONTAB),'TOTAL VENTA',CLASS=A,MSGCLASS=X,
//             NOTIFY=&SYSUID,REGION=0M
//*
//* ---------------------------------------------------------------
//* PASO 1 - COMPILAR Y ENLAZAR EL COBOL DE LA CLASE 041
//* ---------------------------------------------------------------
//COMPILA  EXEC IGYWCL
//COBOL.SYSIN    DD DSN=VLAD.FUENTE.COBOL(TOTVTA),DISP=SHR
//LKED.SYSLMOD   DD DSN=VLAD.LOADLIB(TOTVTA),DISP=SHR
//*
//* ---------------------------------------------------------------
//* PASO 2 - EJECUTARLO, SOLO SI EL PASO ANTERIOR FUE LIMPIO
//* ---------------------------------------------------------------
//EJECUTA  EXEC PGM=TOTVTA
//STEPLIB  DD DSN=VLAD.LOADLIB,DISP=SHR
//SYSOUT   DD SYSOUT=*
//SYSIN    DD *
15000 2 0.10
/*
//

Y con la sintaxis condicional moderna, que es como se escribe hoy:

//  IF (COMPILA.LKED.RC <= 4) THEN
//EJECUTA  EXEC PGM=TOTVTA
//STEPLIB  DD DSN=VLAD.LOADLIB,DISP=SHR
//SYSOUT   DD SYSOUT=*
//SYSIN    DD *
15000 2 0.10
/*
//  ENDIF

Recorrido, línea a línea.

La lección, en una frase: el programa declara qué nombres lógicos usa; el JCL decide a qué apuntan de verdad, en el momento de ejecutar. Cuando en la Parte 9 se hable de configuración externa y de entornos, este es el ejemplo más antiguo y más literal que existe.

🔍 Qué reconocer si vienes de otro mundo

Si conoces… En JCL es…
Un script de shell El JOB completo
command args //PASO EXEC PGM=PROGRAMA,PARM='...'
< entrada.txt //SYSIN DD DSN=... o //SYSIN DD * con datos en línea
> salida.txt //SALIDA DD DSN=...,DISP=(NEW,CATLG)
$PATH //STEPLIB DD DSN=...
Variable de entorno Parámetro simbólico (&VAR) y // SET VAR=valor
cmd1 && cmd2 COND= o IF (PASO.RC = 0) THEN
needs: de GitHub Actions La secuencia de pasos con sus condiciones de código de retorno
Función reutilizable Procedimiento catalogado (PROC … PEND)
Volumen de Docker La sentencia DD: monta un recurso externo con un nombre lógico
docker run --memory REGION=

⚠️ Errores comunes al leerlo

📚 Fuentes y bibliografía


⏮️ Volver al Atlas · 🧟 Los lenguajes que siguen vivos · 🔗 Relacionadas: COBOL · PL/I · RPG