JCL Pro: Углубленное изучение, процедуры и системные утилиты z/OS

Курс предназначен для детального разбора сложных конструкций JCL, включая условную логику, вложенные процедуры и управление поколениями данных. Мы разберем реальные примеры использования утилит IDCAMS и SORT, а также методы устранения аварийных завершений задач.

1. Логика управления потоком: детальный разбор параметра COND и конструкций IF/THEN/ELSE/ENDIF

Логика управления потоком: детальный разбор параметра COND и конструкций IF/THEN/ELSE/ENDIF

В мире мейнфреймов редко встречаются задания (Jobs), которые выполняются строго линейно от первого шага до последнего без каких-либо условий. Реальные бизнес-процессы требуют гибкости: если шаг сортировки данных завершился с ошибкой, нет смысла запускать шаг генерации отчета. Если база данных пуста, программу обновления нужно пропустить.

В JCL (Job Control Language) управление потоком выполнения — это критически важный навык. В этой статье мы детально разберем два основных механизма ветвления: классический (и часто запутанный) параметр COND и более современную, читаемую конструкцию IF/THEN/ELSE.

Концепция кодов возврата (Return Codes)

Прежде чем управлять потоком, нужно понять, на чем основываются решения. Любая программа, завершая работу в среде z/OS, возвращает системе числовой код завершения — Return Code (RC). Этот код помещается в регистр 15 процессора при выходе из программы.

Стандартные значения кодов возврата, принятые в индустрии (хотя программист может определить свои):

| Код (RC) | Значение | Описание | | :--- | :--- | :--- | | 0000 | OK | Успешное выполнение, ошибок нет. | | 0004 | WARNING | Предупреждение. Программа отработала, но были незначительные проблемы (например, пустой файл). | | 0008 | ERROR | Ошибка. Часть данных не обработана или логика нарушена. | | 0012 | SEVERE | Серьезная ошибка. Выполнение невозможно продолжить корректно. | | 0016 | TERMINAL | Фатальная ошибка. Аварийное завершение. |

Именно эти числа мы анализируем, чтобы решить: запускать следующий шаг или нет.

Параметр COND: Классический подход

Параметр COND (Condition) — это старейший способ управления выполнением шагов. Его главная особенность, которая сбивает с толку новичков, заключается в обратной логике.

> В JCL параметр COND задает условие для ПРОПУСКА (bypass) шага, а не для его выполнения.

Если условие, описанное в COND, истинно (TRUE), то шаг НЕ выполняется.

Синтаксис параметра COND

Параметр может быть указан как на уровне задания (JOB), так и на уровне шага (EXEC).

Где: * код — числовая константа, с которой мы сравниваем код возврата. * оператор — логический оператор сравнения. шаг (опционально) — имя конкретного предыдущего шага, чей код возврата мы проверяем. Если не указано, проверяются коды возврата всех* предыдущих шагов.

!Логическая схема работы параметра COND: истинность условия ведет к пропуску действия.

Операторы сравнения

В JCL используются мнемонические коды для операторов:

* GT (Greater Than) — Больше () * GE (Greater or Equal) — Больше или равно () * EQ (Equal) — Равно () * NE (Not Equal) — Не равно () * LT (Less Than) — Меньше () * LE (Less or Equal) — Меньше или равно ()

Формула проверки условия

Чтобы понять, будет ли пропущен шаг, система проверяет следующее неравенство:

Где — это константа, указанная вами в JCL, — оператор сравнения (GT, LT и т.д.), а — реальный код возврата (Return Code) предыдущего шага.

Если это выражение истинно — шаг пропускается.

Примеры и разбор логики

Рассмотрим самый частый пример. Мы хотим запустить шаг STEP2 только если STEP1 завершился успешно (RC=0).

Неправильная логика (как думают новички): "Запустить, если RC равно 0". Правильная логика JCL (COND): "Пропустить, если RC не равно 0".

Код:

Разберем COND=(0,NE,STEP1):

  • Константа: 0
  • Оператор: NE (не равно)
  • Проверка:
  • Если STEP1 вернул 4 (Warning): — это Истина (True). Результат: STEP2 пропускается.

    Если STEP1 вернул 0 (OK): — это Ложь (False). Результат: STEP2 выполняется.

    #### Еще примеры:

    * COND=(4,LT): Пропустить, если 4 меньше RC (то есть, если RC > 4). Это означает: "Выполнять только если RC <= 4" (допускаем 0 и 4). * COND=(0,EQ): Пропустить, если 0 равно RC. Это означает: "Выполнять только если RC не равно 0" (обычно используется для обработки ошибок).

    Специальные параметры: EVEN и ONLY

    Существуют два особых значения для COND, которые меняют поведение при аварийном завершении (ABEND) предыдущих шагов.

  • COND=EVEN: Шаг выполняется, даже если предыдущий шаг завершился аварийно (ABEND). Обычно используется для шагов очистки (cleanup).
  • COND=ONLY: Шаг выполняется только если предыдущий шаг завершился аварийно.
  • Пример комбинирования:

    Здесь STEP3 запустится, даже если был ABEND, НО также будет проверено условие 4 < RC от STEP1. Если условие истинно, шаг все равно будет пропущен, несмотря на EVEN.

    Конструкция IF/THEN/ELSE/ENDIF

    Введенная позже для упрощения жизни системных программистов, конструкция IF/THEN/ELSE работает по привычной для всех логике: "Если условие истинно — ВЫПОЛНИТЬ".

    Синтаксис

    Ключевые отличия от COND

  • Прямая логика: IF (RC = 0) значит "Делай, если 0".
  • Читаемость: Код гораздо понятнее для сопровождения.
  • Гибкость: Поддержка сложных логических выражений с AND, OR, NOT.
  • Операторы в IF

    Можно использовать как мнемоники (GT, EQ), так и символы: * > (GT) * < (LT) * = (EQ) * != или ¬= (NE) * >= (GE) * <= (LE)

    Также используются логические связки: * & или AND * | или OR * ¬ или NOT

    Примеры использования

    #### Пример 1: Простая последовательность Запустить STEP2, только если STEP1 завершился успешно (RC=0).

    #### Пример 2: Сложное условие Запустить STEP3, если STEP1 прошел без ошибок, ИЛИ если STEP2 вернул Warning (RC=4).

    #### Пример 3: Проверка ABEND Конструкция IF также позволяет проверять на аварийное завершение с помощью ключевых слов ABEND и ABENDCC.

    Сравнение COND и IF/THEN

    Давайте сравним реализацию одной и той же логики: "Выполнить STEP2, только если RC STEP1 меньше или равен 4".

    Вариант с COND: Нам нужно условие для пропуска. Если мы хотим выполнять при , значит, пропускать нужно при . В терминах COND (): .

    Вариант с IF: Пишем условие для выполнения.

    Очевидно, что вариант с IF воспринимается человеком быстрее и с меньшей вероятностью ошибки.

    Лучшие практики

  • Используйте IF/THEN для нового кода. Это стандарт де-факто для современной разработки на z/OS. Это снижает порог входа для новых сотрудников.
  • Понимайте COND для поддержки легаси. Огромное количество JCL, написанного 20-30 лет назад, использует COND. Вы обязаны уметь читать его "на лету".
  • Осторожнее с COND на уровне JOB. Если вы напишете COND=(4,LT) в первой строке //JOB, это условие будет применяться ко всем шагам. Если любой шаг вернет RC > 4, все последующие шаги будут пропущены.
  • Проверяйте синтаксис. В IF обязательно наличие ENDIF. Отсутствие закрывающего тега приведет к JCL Error.
  • Заключение

    Управление потоком — это то, что превращает набор команд в интеллектуальный сценарий. Понимание "обратной" логики COND отличает новичка от профессионала, а умелое использование IF/THEN делает ваши скрипты надежными и читаемыми. В следующей статье мы рассмотрим работу с процедурами (PROC), где эти знания пригодятся для создания переиспользуемых шаблонов.

    2. Мастерство работы с процедурами: Cataloged и Instream PROCs, символические параметры и оверрайды

    Мастерство работы с процедурами: Cataloged и Instream PROCs, символические параметры и оверрайды

    В программировании существует золотое правило: DRY (Don't Repeat Yourself) — не повторяйся. Если вы пишете один и тот же код дважды, его нужно вынести в функцию. В мире JCL (Job Control Language) роль функций выполняют Процедуры (Procedures), или сокращенно PROCs.

    Представьте, что у вас есть сложный процесс резервного копирования, состоящий из 10 шагов. Этот процесс нужно запускать для 50 разных баз данных. Копировать 10 шагов 50 раз — это кошмар поддержки. Если изменится имя утилиты, вам придется править код в 500 местах. Процедуры решают эту проблему, позволяя написать логику один раз и вызывать её с разными параметрами.

    В этой статье мы разберем анатомию процедур, научимся делать их гибкими с помощью символических параметров и освоим искусство переопределения (overrides).

    Типы процедур: Instream и Cataloged

    В z/OS существует два способа объявления процедур. Разница между ними заключается лишь в месте их хранения и области видимости.

    1. Instream Procedures (Внутрипотоковые процедуры)

    Эти процедуры описываются непосредственно в самом JCL-файле задания, перед первым шагом выполнения (EXEC).

    * Область видимости: Только текущее задание (Job). * Назначение: Идеальны для разработки и тестирования. Вам не нужно просить системного администратора обновлять библиотеку каждый раз, когда вы меняете строчку кода.

    Синтаксис: Процедура начинается с оператора PROC и заканчивается оператором PEND.

    2. Cataloged Procedures (Каталогизированные процедуры)

    Это процедуры, сохраненные как отдельные члены (members) в специальных библиотеках (Partitioned Data Sets — PDS), известных как PROCLIB. Обычно это системные библиотеки вроде SYS1.PROCLIB или пользовательские библиотеки, определенные администраторами.

    * Область видимости: Любое задание в системе, имеющее доступ к библиотеке. * Назначение: Промышленная эксплуатация (Production). Стандартные задачи для всей компании.

    Особенность: Для каталогизированных процедур оператор PEND является опциональным (хотя его использование считается хорошим тоном), а оператор PROC обязателен только если вы хотите задать параметры по умолчанию.

    [VISUALIZATION: Схема, разделенная на две части. Слева изображен JCL-файл, внутри которого находится блок кода с подписью 'Instream PROC'. Справа изображен JCL-файл, который стрелкой ссылается на иконку библиотеки (книжная полка) с подписью 'PROCLIB', откуда извлекается 'Cataloged PROC'. Схема демонстрирует разницу в месте хранения кода.]

    Символические параметры (Symbolics)

    Процедура, которая делает всегда одно и то же (например, копирует файл A в файл B), бесполезна для массового использования. Нам нужна гибкость: копировать файл X в файл Y сегодня, и Z в W завтра.

    Для этого используются символические параметры. В теле процедуры они обозначаются знаком амперсанда & перед именем.

    Определение и использование

    Рассмотрим процедуру, которая печатает содержимое набора данных.

    В строке PROC мы определили параметр &DSN и дали ему значение по умолчанию. Если пользователь не укажет свой файл, процедура распечатает SYS1.MACLIB.

    Передача параметров при вызове

    При вызове процедуры мы можем заменить значение &DSN на любое другое:

    В момент выполнения JCL-интерпретатор (Converter/Interpreter) физически подставит текст 'MY.DATA.SET' везде, где встретит &DSN внутри процедуры.

    Правила работы с символиками

  • Длина: Имя параметра не должно превышать 8 символов (не считая &).
  • Обязательность: Если вы использовали &VAR в коде, но не задали значение по умолчанию в PROC и не передали его в EXEC, задание завершится с JCL Error.
  • Null-значения: Можно передать пустое значение, чтобы удалить часть кода: PARM= (без значения).
  • Оверрайды (Overrides): Изменение без изменения кода

    Это, пожалуй, самая мощная и сложная для понимания часть работы с JCL. Оверрайд позволяет вам изменить параметры конкретного шага (DD или EXEC) внутри процедуры, не меняя сам исходный код процедуры.

    Представьте, что в процедуре жестко прописан вывод отчета на принтер (Class A), а вам нужно именно сейчас сохранить его в файл, но менять процедуру в библиотеке запрещено.

    Синтаксис оверрайда

    Оверрайды пишутся в вызывающем JCL после строки EXEC PROC=....

    Формат ссылки на DD-statement: //ИмяШагаВызова.ИмяШагаВПроцедуре.ИмяDD DD ...

    Однако, в стандартном JCL (без вложенных процедур) формат упрощается до: //ИмяШагаВПроцедуре.ИмяDD DD ...

    Давайте разберем на примере.

    Исходная процедура (MYPROC):

    Ваш JCL с оверрайдами:

    Что произошло:

  • Для DD1: Мы полностью заменили определение набора данных. Вместо DATA.OLD программа будет читать DATA.NEW.
  • Для DD2: Мы изменили класс вывода с A на X.
  • Правила оверрайдов

  • Порядок имеет значение: Оверрайды должны следовать в том же порядке, в котором шаги (STEP) описаны в процедуре. Если вы попытаетесь переопределить что-то в STEP2 перед STEP1, вы получите ошибку (в старых версиях JES, современные системы умнее, но лучше соблюдать порядок).
  • Слияние параметров: Если вы переопределяете DD-statement, вы меняете только те параметры, которые указали явно. Остальные параметры берутся из процедуры.
  • Исключение:* Если вы меняете DSN, то параметры VOL и UNIT из процедуры могут сброситься, если они несовместимы.
  • Добавление DD: Если вы укажете имя DD, которого нет в процедуре, оно будет добавлено к шагу. Это полезно для добавления дополнительных библиотек (например, в STEPLIB).
  • Оверрайд параметров EXEC

    Вы также можете изменить параметры самого запуска программы (например, PARM, TIME, REGION).

    Обратите внимание: здесь синтаксис КЛЮЧ.ШАГ=ЗНАЧЕНИЕ пишется прямо в строке вызова процедуры.

    Практический пример: Универсальная компиляция

    Рассмотрим классический пример использования процедур — компиляция COBOL программы. Никто не пишет шаги компиляции и линковки вручную.

    Процедура COBCL (Compile & Link):

    Как мы её используем:

  • Простая компиляция:
  • Результат: Компилируется MY.SOURCE(PROG01), модуль кладется в MY.LOAD(PROG01).

  • Компиляция с отладкой (Оверрайд):
  • Нам нужно добавить библиотеку отладки в шаг линковки (LKED). Результат: Мы добавили SYSLIB к шагу LKED, не трогая процедуру.

    Заключение

    Процедуры — это фундамент модульности в JCL. Использование Instream процедур ускоряет разработку, Cataloged процедуры обеспечивают стандартизацию, символические параметры дают гибкость, а оверрайды позволяют адаптировать стандартные процессы под уникальные ситуации.

    В следующей статье мы углубимся в работу с системными утилитами, начав с легендарной IDCAMS, и узнаем, как управлять наборами данных VSAM.

    3. Управление версионностью данных: создание и обслуживание Generation Data Groups (GDG) на практике

    Управление версионностью данных: создание и обслуживание Generation Data Groups (GDG) на практике

    В современной IT-инфраструктуре управление историческими данными — это стандартная задача. Логи транзакций, ежедневные бэкапы, ежемесячные отчеты — все эти файлы имеют одинаковую структуру, но разное содержание в зависимости от времени создания. В мире Windows или Linux мы часто решаем эту проблему, добавляя дату к имени файла: report_2023_10_01.txt, report_2023_10_02.txt. Но это требует динамического изменения скриптов запуска.

    В z/OS существует элегантное архитектурное решение, встроенное в саму файловую систему, — Generation Data Groups (GDG). Это механизм, который позволяет ссылаться на данные не по их физическому имени, а по их относительному поколению (версии).

    В этой статье мы разберем, как создавать базы GDG, управлять поколениями через JCL и настраивать политики устаревания данных.

    Что такое GDG?

    Generation Data Group (GDG) — это группа наборов данных, связанных хронологически. Она состоит из двух компонентов:

  • GDG Base (База): Запись в каталоге (Catalog), которая хранит правила для группы (сколько версий хранить, как удалять старые). Сама по себе база данных не содержит, это лишь «контейнер».
  • GDS (Generation Data Sets): Реальные физические файлы (поколения), привязанные к этой базе.
  • Абсолютные и относительные имена

    Система z/OS автоматически присваивает каждому поколению уникальное абсолютное имя. Оно формируется путем добавления суффикса GxxxxVyy к имени базы.

    Например, если база называется PROD.BILLING.DAILY, то файлы на диске будут выглядеть так: * PROD.BILLING.DAILY.G0045V00 (самый старый) * PROD.BILLING.DAILY.G0046V00 * PROD.BILLING.DAILY.G0047V00 (самый новый)

    Однако в JCL мы редко используем эти длинные имена. Мы используем относительную адресацию:

    * (0) — Текущее (последнее созданное) поколение. * (+1) — Новое поколение, которое мы хотим создать. * (-1), (-2) — Предыдущие поколения (история).

    [VISUALIZATION: Схема структуры GDG. В центре находится папка с подписью 'GDG Base: MY.DATA'. От неё отходят стрелки к трем файлам, расположенным друг за другом. Первый файл подписан 'G0001V00 (-1)', второй 'G0002V00 (0)', третий (полупрозрачный, создается) 'G0003V00 (+1)'. Схема демонстрирует связь абсолютных имен и относительных ссылок.]

    Создание GDG Base с помощью IDCAMS

    Прежде чем вы сможете создать файл (+1), вы должны один раз определить базу. Это делается с помощью системной утилиты IDCAMS (Access Method Services).

    Вот стандартный шаг JCL для создания базы:

    Разбор параметров DEFINE GDG

    Это критически важные настройки, определяющие жизненный цикл ваших данных:

  • NAME: Имя базы. Оно должно соответствовать стандартам именования вашего сайта.
  • LIMIT(n): Максимальное количество поколений, которое система будет хранить в каталоге. Максимум — 255. Когда создается поколение , самое старое будет удалено из списка.
  • SCRATCH / NOSCRATCH:
  • * SCRATCH (Рекомендуется): Когда поколение «выпадает» из лимита, запись о нем удаляется из каталога И физический файл удаляется с диска (освобождается место). * NOSCRATCH: Запись удаляется из каталога, но файл остается на диске. Он становится «некаталогизированным» (uncataloged). Найти его можно будет только зная метку тома (Volume Serial). Это часто приводит к засорению дискового пространства.
  • EMPTY / NOEMPTY:
  • NOEMPTY (Стандарт): При превышении лимита удаляется только самое старое* поколение. EMPTY: При превышении лимита удаляются ВСЕ* существующие поколения. Используется крайне редко, обычно для временных рабочих групп.

    Использование GDG в JCL

    После создания базы мы можем использовать относительную адресацию в наших заданиях.

    Создание нового поколения (+1)

    Чтобы создать новый файл, мы указываем (+1) и статус NEW. Важно: статус CATLG обязателен при нормальном завершении, иначе поколение не попадет в базу.

    Важный нюанс: В момент запуска шага система резервирует имя GxxxxV00. Если задание упадет (Abend) и вы перезапустите его, система попытается использовать то же самое имя GxxxxV00. Если предыдущий запуск успел создать файл (даже пустой), вы получите ошибку DUPLICATE NAME. Поэтому в DISP третьим параметром стоит DELETE — при ошибке файл удалится, и перезапуск пройдет чисто.

    Чтение текущего поколения (0)

    Эта конструкция всегда будет читать самую свежую существующую версию.

    Чтение предыдущих версий (-n)

    Если вам нужно сравнить данные за сегодня и вчера:

    Обработка всех поколений сразу (GDG ALL)

    Иногда нужно прочитать все доступные исторические данные (например, для месячного отчета). Для этого достаточно указать имя базы без скобок:

    Система динамически склеит (concatenation) все активные поколения от самого нового к самому старому (или наоборот, в зависимости от настроек системы, но чаще всего порядок — от старых к новым).

    Логика "Прокрутки" (Roll-in)

    Один из самых сложных моментов для понимания — это момент, когда (+1) становится (0).

    > Обновление каталога GDG происходит в конце задания (Job), а не в конце шага (Step).

    Рассмотрим пример задания с двумя шагами:

    В STEP2 мы обращаемся к тому же файлу, который создали в STEP1. Мы должны использовать (+1), потому что для системы в рамках этого задания этот файл все еще является «будущим» поколением. Он станет (0) только после того, как MYJOB полностью завершится.

    Если бы мы написали в STEP2 DSN=MY.GDG(0), мы бы прочитали файл, который был создан вчера (до начала этого джоба).

    Обслуживание и изменение GDG

    Требования бизнеса меняются. Вчера нужно было хранить данные за 5 дней, сегодня — за 30.

    Изменение лимита (ALTER)

    Вам не нужно удалять и пересоздавать базу. Используйте команду ALTER утилиты IDCAMS:

    Если вы уменьшаете лимит (например, с 30 до 5), лишние старые поколения не удалятся мгновенно. Они будут удаляться по одному при каждом создании нового поколения, пока их количество не сравняется с новым лимитом.

    Полное удаление (DELETE FORCE)

    Если вы попытаетесь удалить базу GDG командой DELETE PROD.LOGS.DAILY, вы получите ошибку, если внутри есть активные поколения. Чтобы удалить базу вместе со всеми файлами, используйте параметр FORCE:

    Лучшие практики

  • Всегда используйте SCRATCH. Оставление старых файлов на дисках без каталогизации (NOSCRATCH) — главная причина нехватки места в системах хранения.
  • Используйте DISP=(NEW,CATLG,DELETE). Это спасет вас от ручного удаления «битых» файлов при перезапуске упавших джобов.
  • Осторожнее с параллельным доступом. Если два джоба одновременно пытаются создать (+1) для одной базы, возникнет конфликт блокировок каталога или ошибка дублирования имен. Планируйте расписание так, чтобы создание версий шло последовательно.
  • Модели (Model DSCB) больше не нужны. В старых книгах по JCL вы можете встретить требование указывать DCB=модель при создании GDG. В современных системах, управляемых SMS (Storage Management Subsystem), это больше не требуется.
  • Заключение

    GDG — это мощный инструмент автоматизации, который избавляет разработчика от необходимости писать скрипты для управления именами файлов и очистки старых данных. Правильно настроенная база GDG работает годами без вмешательства человека, обеспечивая надежную ротацию логов и бэкапов.

    В следующей статье мы перейдем к более сложным структурам данных и детально изучим VSAM (Virtual Storage Access Method) — файловую систему, на которой держится высокопроизводительная обработка транзакций в z/OS.

    4. Системные утилиты в деталях: IDCAMS для VSAM, DFSORT и IEBGENER с примерами кода

    Системные утилиты в деталях: IDCAMS для VSAM, DFSORT и IEBGENER с примерами кода

    В предыдущих статьях мы научились управлять потоком выполнения заданий и создавать переиспользуемые процедуры. Теперь пришло время заглянуть «под капот» z/OS и познакомиться с инструментами, которые выполняют реальную работу с данными.

    JCL — это лишь язык управления. Сам по себе он не копирует файлы, не сортирует записи и не создает базы данных. Эту работу выполняют системные утилиты — стандартные программы, поставляемые вместе с операционной системой. В арсенале системного программиста их десятки, но три из них являются абсолютным фундаментом: IEBGENER, IDCAMS и DFSORT.

    В этой статье мы разберем их синтаксис, типовые сценарии использования и оптимизацию.

    IEBGENER: Классика копирования

    IEBGENER — это одна из старейших утилит в z/OS. Её основное назначение — последовательное копирование наборов данных. Несмотря на свой возраст, она используется в каждом втором джобе.

    Основные функции

  • Копирование последовательного набора данных (PS) в другой PS.
  • Копирование члена библиотеки (PDS Member) в PS.
  • Создание резервной копии PDS (преобразование в последовательный формат для выгрузки на ленту).
  • Синтаксис и пример использования

    Для работы IEBGENER требуются четыре стандартных DD-имени: * SYSUT1: Входной набор данных (откуда копируем). * SYSUT2: Выходной набор данных (куда копируем). * SYSPRINT: Лог работы утилиты. * SYSIN: Управляющие команды. Если мы просто копируем файл «как есть», здесь указывается DUMMY.

    Пример простого копирования:

    > Совет эксперта: В современных системах часто используется программа ICEGENER. Это алиас (псевдоним) для DFSORT, который эмулирует поведение IEBGENER, но работает значительно быстрее за счет оптимизации ввода-вывода. В JCL вы по-прежнему пишете PGM=IEBGENER, но система незаметно подменяет её на более эффективный движок.

    IDCAMS: Швейцарский нож для VSAM

    Если IEBGENER работает с простыми плоскими файлами, то для сложных структур данных используется IDCAMS (Integrated Data Cluster Access Method Services). Это основной инструмент для работы с файловой системой VSAM (Virtual Storage Access Method).

    VSAM — это не просто файл, это сложная структура, которая может поддерживать индексы для быстрого поиска по ключу. Поэтому мы не можем просто создать VSAM через JCL-параметр DISP=NEW. Нам нужно «определить» (Define) его структуру.

    Архитектура VSAM KSDS

    Самый популярный тип VSAM — это KSDS (Key Sequenced Data Set). Он состоит из двух компонентов:

  • Data Component: Здесь хранятся сами данные.
  • Index Component: Здесь хранятся ключи и указатели на данные (аналог B-дерева).
  • [VISUALIZATION: Схема структуры VSAM KSDS. Сверху расположен блок 'Index Component', содержащий узлы дерева с ключами. От нижних узлов индекса идут стрелки к блокам ниже, подписанным 'Data Component (Control Intervals)'. В блоках данных изображены записи с ключами. Схема показывает, как индекс ссылается на физическое расположение данных.]

    Команда DEFINE CLUSTER

    Создание VSAM набора данных называется определением кластера. Рассмотрим пример создания телефонного справочника, где ключом является номер телефона (первые 10 байт).

    Разберем ключевые параметры: * INDEXED: Указывает, что мы создаем KSDS (с индексом). * KEYS(10 0): Ключ имеет длину 10 байт и начинается со смещения 0 (с самого начала записи). * RECORDSIZE(80 80): Средняя и максимальная длина записи. Здесь фиксированная длина 80. * FREESPACE(10 20): Резерв свободного места для будущих вставок. 10% в каждом блоке (CI) и 20% в каждой области (CA).

    Расчет записей в Control Interval

    Понимание того, сколько записей поместится в один блок ввода-вывода (Control Interval — CI), критично для производительности. Формула для расчета:

    Где: * — количество записей в одном CI (округляется вниз). * — размер Control Interval (обычно 4096 байт). * — служебный заголовок CI (обычно 10 байт). * — длина одной записи.

    Если , то . Значит, в один блок физически поместится 51 запись.

    Управление данными: REPRO и DELETE

    IDCAMS также используется для копирования данных в VSAM (так как IEBGENER этого не умеет) и удаления.

    Загрузка данных (REPRO):

    Удаление (DELETE):

    DFSORT: Мастер манипуляции данными

    DFSORT (Data Facility Sort) — это, пожалуй, самый мощный инструмент в арсенале. Новички думают, что он нужен только для сортировки (А-Я). Профессионалы используют его для фильтрации, форматирования, суммирования и анализа данных без написания кода на COBOL или PL/I.

    Базовая сортировка (SORT)

    Синтаксис команды SORT опирается на позиционирование байтов.

    Разбор FIELDS=(Start, Length, Format, Order):

  • 1,4,CH,A: Начинаем с 1-го байта, берем 4 байта, интерпретируем как символы (CH), сортируем по возрастанию (Ascending).
  • 10,2,PD,D: Если первые поля равны, берем поле с 10-го байта, длина 2, формат Packed Decimal (PD), сортируем по убыванию (Descending).
  • Фильтрация (INCLUDE / OMIT)

    Зачем обрабатывать миллион записей, если нужны только данные за конкретный филиал? Используйте INCLUDE (оставить) или OMIT (исключить).

    Здесь FIELDS=COPY означает, что сортировка не требуется (просто копирование), но фильтр INCLUDE оставит только записи, где в позиции 20 находится 'NYC' или 'LON'.

    Реформатирование (OUTREC / INREC)

    DFSORT позволяет перекраивать структуру записи «на лету». Это невероятно полезно для создания отчетов или подготовки данных для других систем.

    Представьте, что у нас есть запись 80 байт, а нам нужно создать новую запись, где:

  • Сначала идет дата (байты 70-78).
  • Потом пробел.
  • Потом Фамилия (байты 1-20).
  • Команда OUTREC (Output Record) формирует новую структуру выходного файла, собирая его как конструктор из кусков входной записи и литералов (констант).

    Сравнение утилит

    | Задача | IEBGENER | IDCAMS | DFSORT | | :--- | :--- | :--- | :--- | | Простое копирование PS -> PS | ✅ (Стандарт) | ✅ (Через REPRO) | ✅ (OPTION COPY) | | Работа с VSAM | ❌ | ✅ (Основной инструмент) | ✅ (Может читать/писать) | | Сортировка данных | ❌ | ❌ | ✅ | | Фильтрация записей | ❌ | ❌ | ✅ | | Изменение формата записи | ❌ | ❌ | ✅ | | Удаление/Создание каталога | ❌ | ✅ | ❌ |

    Заключение

    Умение комбинировать эти три утилиты позволяет решать 90% задач по обработке данных без привлечения разработчиков приложений.

    * Используйте IEBGENER для простых бэкапов. * Используйте IDCAMS для управления жизненным циклом VSAM и каталогов. * Используйте DFSORT для любой логики трансформации, фильтрации и упорядочивания данных.

    В следующей части курса мы рассмотрим продвинутые техники отладки JCL и работу с системным логом, чтобы вы могли быстро находить причины ошибок Abend.

    5. Отладка и оптимизация: анализ JCL ошибок, System Abends и работа с выводом SDSF

    Отладка и оптимизация: анализ JCL ошибок, System Abends и работа с выводом SDSF

    В предыдущих статьях мы научились писать сложный JCL, использовать процедуры и управлять данными. Но давайте будем честны: даже у экспертов с 20-летним стажем задания падают с ошибками. Разница между новичком и профессионалом не в том, что профессионал не делает ошибок, а в том, насколько быстро он может найти причину и исправить её.

    В среде z/OS нет всплывающих окон с подсказками «Вы забыли точку с запятой». Здесь есть коды завершения, системные дампы и логи JES. В этой статье мы научимся читать эти «шифровки», разберем самые страшные абенды (Abends) и освоим работу в SDSF — главном инструменте отладки на мейнфрейме.

    Анатомия сбоя: JCL Error vs Abend

    Первое, что нужно понять: на каком этапе упало задание. Жизненный цикл джоба делится на две фазы: интерпретация и выполнение.

    1. JCL Error (Ошибка синтаксиса)

    Это происходит до того, как ваша программа начала выполняться. Система (JES — Job Entry Subsystem) читает ваш код, проверяет синтаксис, наличие указанных наборов данных (если DISP=OLD) и доступность устройств.

    Симптомы: * Статус задания в SDSF: JCL ERR. * Программа не запустилась ни на секунду.

    Типичные причины: * Опечатки в ключевых словах (DSN вместо DSNAME — допустимо, но DS — нет). * Отсутствие пробелов там, где они нужны, или наличие там, где их быть не должно. * Непарные скобки. * Ссылка на несуществующий шаг в параметре COND.

    > Совет: Используйте параметр TYPRUN=SCAN в карте JOB. Это заставит систему проверить синтаксис всего задания без его реального запуска. Это сэкономит вам часы, если джоб должен был ждать очереди на выполнение.

    2. Abend (Abnormal End — Аварийное завершение)

    Это происходит во время выполнения. Синтаксис верен, ресурсы выделены, программа запустилась, но что-то пошло не так. Абенды делятся на два типа:

    * System Abend (Sxxx): Ошибку обнаружила операционная система z/OS (например, попытка чтения за пределами файла). * User Abend (Uxxxx): Ошибку обнаружила сама прикладная программа и решила прекратить работу (например, нарушение бизнес-логики).

    [VISUALIZATION: Временная шкала выполнения задания. Слева точка 'Submission' (Отправка). Далее отрезок 'Conversion/Interpretation'. Над ним молния с подписью 'JCL Error'. Далее отрезок 'Execution' (Выполнение). Над ним взрыв с подписью 'Abend (Sxxx/Uxxxx)'. В конце точка 'Output' (Вывод). Схема показывает, что JCL Error случается до выполнения, а Abend — во время.]

    Топ-5 системных абендов (System Abends)

    Коды системных ошибок шестнадцатеричные. Знание этих пяти кодов покрывает 90% проблем разработчика.

    S0C7 (System 0C7) — Data Exception

    Король всех ошибок в COBOL. Означает «Ошибка данных». Программа попыталась выполнить математическую операцию над нечисловыми данными.

    Причина: Вы определили поле как числовое (например, PIC 9(5)), но в файле там лежат пробелы, буквы или бинарный мусор. Лечение: Смотреть дамп памяти или лог программы, искать, какая запись обрабатывалась в момент падения, и проверять входные данные.

    S0C4 (System 0C4) — Protection Exception

    Аналог Segmentation Fault в Linux или Windows. Программа попыталась обратиться к участку памяти, который ей не принадлежит.

    Причина: Ошибка работы с указателями, выход за границы массива (таблицы) в коде программы или неправильные параметры вызова подпрограммы. Лечение: Это ошибка кода программы, а не JCL. Требуется перекомпиляция и отладка кода.

    S806 — Module Not Found

    Система не смогла найти программу, которую вы указали в EXEC PGM=....

    Причина:

  • Опечатка в имени программы.
  • Программа лежит в личной библиотеке, но вы забыли указать STEPLIB.
  • Лечение: Проверьте имя программы и наличие нужной библиотеки в STEPLIB или JOBLIB.

    x37 (B37, D37, E37) — Out of Space

    Группа ошибок, связанных с нехваткой дискового пространства.

    * B37: Закончилось место на томе (диске), и система не может найти место для расширения. * D37: Достигнут лимит экстентов (фрагментов). Файл разбит на слишком много мелких кусков (обычно 16), и больше добавлять нельзя. * E37: Нехватка места в PDS-библиотеке (Directory full) или на томе.

    Лечение: Увеличить параметры SPACE в JCL (например, SPACE=(CYL,(50,10))) или сжать библиотеку (Compress).

    S013 — Open Error

    Ошибка при открытии файла. Обычно означает конфликт атрибутов.

    Причина: В JCL вы указали LRECL=80, а программа ожидает LRECL=100. Или размер блока (BLKSIZE) не кратен длине записи. Лечение: Проверить соответствие DCB параметров в JCL и в коде программы.

    SDSF: Окно в систему

    SDSF (System Display and Search Facility) — это интерфейс, через который мы взаимодействуем с заданиями. Это не просто «просмотрщик логов», это пульт управления.

    Основные панели

    Для навигации используются команды в командной строке:

  • ST (Status): Показывает статус всех заданий. Это ваш главный экран.
  • DA (Display Active): Показывает, что выполняется прямо сейчас (нагрузка на CPU).
  • I (Input): Очередь на вход (задания, ожидающие выполнения).
  • O (Output): Очередь на выход (готовые отчеты).
  • Фильтрация

    В системе крутятся тысячи заданий. Чтобы найти свои, используйте команды фильтрации:

    * OWNER userid — показать задания конкретного пользователя. PREFIX jobname — показать задания, начинающиеся с определенного имени.

    Анализ вывода (Drill down)

    Когда задание завершилось (успешно или с ошибкой), напротив него в панели ST нужно поставить вопросительный знак ? и нажать Enter. Это раскроет структуру вывода задания (DD-names).

    Ключевые файлы логов:

  • JESMSGLG: Здесь находятся сообщения от системы JES. Тут вы увидите время запуска, время окончания и коды завершения каждого шага (STEP WAS EXECUTED - COND CODE 0000).
  • JESYSMSG: Системные сообщения JCL. Здесь подробно расписано, какие файлы были выделены (Allocated), какие удалены, и где именно произошла синтаксическая ошибка.
  • SYSPRINT / SYSOUT: Вывод самих утилит и программ. Если упала сортировка DFSORT, причину нужно искать именно здесь.
  • [VISUALIZATION: Скриншот интерфейса SDSF (схематичный). Таблица со столбцами JOBNAME, OWNER, QUEUE, C (Class), RC (Return Code). На одной из строк в поле команд (слева) стоит символ '?'. Ниже показано раскрытое окно с перечнем DD-имен: JESMSGLG, JESJCL, JESYSMSG, SYSPRINT. Стрелка указывает, что '?' открывает детали.]

    Оптимизация JCL

    Отладка — это исправление ошибок. Оптимизация — это предотвращение проблем и ускорение работы.

    1. Магия BLKSIZE=0

    Раньше программисты вручную высчитывали размер блока (BLKSIZE), чтобы он оптимально ложился на дорожку диска. Сегодня золотое правило: Не указывайте BLKSIZE вручную (за редким исключением).

    Укажите BLKSIZE=0 в параметрах DCB. Система z/OS (через механизм SDB — System Determined Blocksize) сама рассчитает максимально эффективный размер блока для текущего типа диска. Это может ускорить чтение/запись файла на 30-50%.

    2. Управление памятью (REGION)

    Параметр REGION определяет, сколько оперативной памяти доступно вашему шагу.

    * Если указать слишком мало — получите S804 или S878 (Not enough storage). * Если указать REGION=0M, система выдаст всю доступную память. Это удобно, но опасно: «плохая» программа может съесть все ресурсы и подвесить систему.

    Рекомендация: Для промышленных задач ставьте разумные лимиты (например, REGION=64M), а 0M используйте только для отладки или тяжелых утилит типа DB2 Load.

    3. VIO (Virtual I/O) для временных файлов

    Если вам нужен временный файл (&&TEMP), который удалится в конце джоба и он небольшого размера, используйте UNIT=VIO вместо UNIT=SYSDA.

    VIO создает файл не на диске, а в страничной памяти (Paging Space). Это происходит мгновенно, без физических операций ввода-вывода головками диска.

    Заключение

    Умение читать дампы и логи SDSF — это суперсила мейнфрейм-разработчика.

    * Видите JCL Error? Ищите опечатки в JESYSMSG. * Видите S0C7? Проверяйте данные. * Видите B37? Добавляйте SPACE. * Видите S806? Проверяйте STEPLIB.

    Теперь, когда мы умеем писать код, управлять данными и исправлять ошибки, наш курс JCL Pro подходит к концу. Эти знания — фундамент, на котором строятся самые надежные банковские и страховые системы мира.