Привет всем! Возникла задача из программы запускать задание. Собственно, как это сделать - понятно. Но для пробы и сделал простое задание: //TST3RDR JOB CLASS=A,MSGCLASS=S //GENER EXEC PGM=IEBGENER //SYSIN DD DUMMY //SYSPRINT DD SYSOUT=A //SYSUT1 DD DSN=IS0485.TEST.JOBLIB(CLEAJCL2),DISP=SHR //SYSUT2 DD SYSOUT=(*,INTRDR)
Т.е. нужно запустить задание CLEAJCL2. Оно отрабатывает. Но проблема в том, что я не могу найти протокол его работы. А это критично. Нет смысла писать программу, запускающую задание, если прокола не будет. Так вот, собственно, вопрос - почему нет протокола?
А в журнале нет после выполнения, случайно, сообщения типа: $HASP250 CLEAJCL2 PURGED -- (JOB KEY WAS CA08417D) ? Если нет, то может просто в SDSF с OWNER проблемы?
А в журнале нет после выполнения, случайно, сообщения типа:
Нет. Со всякими фильтрами проверил и без фильтра тоже. Я так понимаю, что в этом случае второе задание должно от мого юзера запускаться... Сообщений о чистке тоже не было. Возможно, проблема в настройках самого ридера.
Добавлено (17.08.2012, 15:12) --------------------------------------------- При попытке открытия ридера из программы - код 96... Кругом засады
Добавлено (17.08.2012, 15:28) --------------------------------------------- Как подсказал Инет - код может быть четйрёхзначным, так что код - 9246. Кто знает, где найти коды при открытии файла?
Добавлено (17.08.2012, 15:43) --------------------------------------------- С кодами разобрался - правил текст и ошибся в имени DD карты. Так что код 9246 скорее всего это и означает - файл не найден.
Но проблема с sysout осталась. Нету протокола вторичного задания.
Что и в syslog никаких записей о задании? Хотя бы о завершении шага или о старте?
Заодно извиняюсь перед sager, запись там может и есть, но общий syslog не доступен (только собственные задания), так что ничего наверняка сказать не могу. По моему прошлому опыту - через ридер задания нормально стартовали и протокол был виден. Пока подозреваю, что дело в настройках ридера. Но в описании ничего подходящего не нашёл. Может кто знает, как сделать, что бы протоколы чистились после завершения задания? Это, вообще-то, делается через свойства очередей, но дело в том, что все протоколы сохраняются, если их запускать сабмитом. Так что удаление происходит только в случае запуска именно через ридер.
Написал письмо заказчику, но надежды не сильно большие. Придётся, боюсь, искать другое решение.
как выглядит JOB statement запускаемого задания? //?????? JOB CLASS=A,MSGCLASS=S
схема запуска прекрасно работает и широко используется, в частности, в обслуживаемых мною приложениях, так что все должно работать добавьте NOTIFY=userid в JOB чтобы увидеть сообщения оо втором задании раз уж syslog недоступен
Сообщение отредактировал Gregory - Пн, 20.08.2012, 16:45
Да, всем спасибо, всё заработало. Обычно все протоколы сыпятся в HOLD. При использовании INTRDR протокол направляется OUTPUT. С моим USERID, никаких фильтров даже перестраивать не нужно... По идее, я должен был сразу увидеть всё... Но почему-то не увидел. Пришлось менять фильтры, тратить время на поиск причины, сюда писать.
Ну и ладушки - после письма заказчику всё встало на места (ну и возможность остаётся, что я сам что-то не так смотрел, хотя вроде бы в разных вариантах пытался). Пришлось ещё немного пошерстить доки, что бы заставить задание выводить протокол в HOLD, как все пользователи привыкли уже. Ещё немого дописать прогу, что бы на лету меняла JCL... Но это уже просто.
BTW) запуск последовательности заданий (примитивный суррогат OPC), возможно, кому-нибудь пригодится... В конец каждого задания добавляется следующий шаг (один и тот же для всех):
Code
//SUBMIT EXEC PGM=IKJEFT1B,COND=(0,NE),PARM='%LAUNCH' //SYSPROC DD DISP=SHR,DSN=набор данных с процедурой LAUNCH //JCLLIB DD DISP=SHR,DSN=набор данных с заданиями //INTRDR DD SYSOUT=(*,INTRDR) //SYSTSIN DD DUMMY //SYSTSPRT DD SYSOUT=*
Code
/* REXX Submit the next job from sequence if any */ parse upper arg . cc = 16 /* Find the data set allocated to SYSPROC DD */ call outtrap 'stem.' 'LISTALC STATUS' call outtrap 'off' i = 2 dd.0 = 0 do while i < stem.0 parse var stem.i dsname ddname disp i = i + 1 select when dsname = 'NULLFILE' then nop when dsname = 'TERMFILE' then nop otherwise parse var stem.i 3 ddname +8 disp i = i + 1 end if ddname = '' then do n = dd.0 dd.n = dd.n "'"dsname"'" end else do n = dd.0 + 1 dd.n = ddname "'"dsname"'" dd.0 = n end end found = 0 target = 'JCLLIB' do i = 1 to dd.0 parse var dd.i ddname dsnames if ddname = target then do found = 1 leave i end end i if found = 0 then do say 'DD name 'target' is missed' signal quit end found = 0 if words(dsnames) <> 1 then do say 'DD name 'target' is invalid' signal quit end quote = "'" parse var dsnames (quote) jcllib (quote) .
/* Get the member list of JCLLIB */ members. = 0 call outtrap 'temp.' "LISTDS '"jcllib"' MEMBER" cc = rc call outtrap 'off' if cc <> 0 then do do i = 1 to temp.0 say temp.i end signal quit end /* Skip LISTDS header */ do n = 1 to temp.0 until temp.n = '--MEMBERS--' end n maxjobno = 0 /* create job list and find the max job no */ do i = n+1 to temp.0 parse value temp.i 1 with jobname members.jobname jobno = right(jobname, 3) if datatype(jobno, 'W') = 1 then maxjobno = max(maxjobno, jobno) end i drop temp. /* Extract the jobname of the running job */ jobname = storage(c2x(storage(d2x(x2d(c2x(storage('224',4)))+x2d('AC')),4)),8) jobname = strip(jobname) jobno = right(jobname, 3) /* Look if we really have the next job to submit */ if datatype(jobno, 'W') = 0 then do /* Normally never happens, jobnames should be *nnn */ say 'Invalid job name of the running job 'jobname signal quit end nextjob = '' do i = jobno+1 to maxjobno nextjob = left(jobname, length(jobname)-3)''right(i, 3, '0') if members.nextjob = 1 then leave /* next job present */ end i if nextjob = '' then do cc = 0 signal quit /* Nothing to submit */ end /* To make this automatic job submission more safe, we would like to ensure that we submit exactly the job what we want to run. Check the job card to be ensure that this is really the expected job. */ "ALLOC FI(JCLLIB) DSN('"jcllib"("nextjob")') SHR" if rc \= 0 then do say 'Unable to allocate 'jcllib', ALLOCATE return code is 'rc signal quit end 'EXECIO * DISKR JCLLIB (FINIS STEM JOBCARDS.' if rc \= 0 then do say 'Unable to read job from 'nextjob', EXECIO return code is 'rc signal quit end parse var jobcards.1 '//' truename job . if job \= 'JOB' then do say 'The first card of member 'nextjob' is not a job card' signal quit end if truename \= nextjob then do say 'The jobname 'truename' is not the same as member name 'nextjob signal quit end 'FREE FI(JCLLIB)' 'EXECIO 'jobcards.0' DISKW INTRDR (FINIS STEM JOBCARDS.' cc = rc if rc = 0 then say 'Job 'nextjob' submitted' Quit: exit cc
Здесь предполагается, что задания находятся в библиотеке JCLLIB в виде разделов с именами вида ABC001, ABC002, ... (три последних символа - цифры, длина имени от 4 до 8 символов). Добавленный шаг обеспепечивает запуск следующего задания в последовательности (с большим номером, не обязательно подряд). Задания будет выполняться строго последовательно. Принципиально критерий запуска может быть другим, например, можно получить последовательность запуска из списка и т.д.
Сообщение отредактировал Gregory - Ср, 22.08.2012, 11:34
BTW) запуск последовательности заданий (примитивный суррогат OPC), возможно, кому-нибудь пригодится...
Может когда пригодится. Я на Коболе написал уже. Но там всё заточено под нужды конкретной задачи (нужно экстракт из базы данных писать в разные наборы данных в зависимости от запроса).
и здесь тоже приложение, в котором это использовалось, на основании диалога (ISPF) формировало набор заданий для выполнения задачи, который можно было запустить, стартовав первое задание, причем выполнение этих заданий происходит в другой системе. Последовательное выполнение заданий обусловлено их функциями. Возможно, здесь интерес будут представлять некоторые фрагменты кода
Сообщение отредактировал Gregory - Ср, 22.08.2012, 11:43
Витиевато Надо запомнить, где искать, если вдруг чего... У меня дело осложняется тем, что заказчик точно не знает, что именно нужно. Т.е. знает, что нужны данные из базы. Но как это потом будет функционировать... Я сильно подозреваю, что эти экстракты будут использоваться для синхронизации IMS базы с какой-то другой (пока не понятно, какой именно) на Intel. И скорее всего пользоваться этим будут достаточно часто, так что возникнет вопрос о запуске задания из-под Web... Или как-то так ещё... Если есть наколка по этой теме - буду признателен
первый шаг функциональный - выборка данных из DB2, SMP/E и т.д. и формирование отчета, это может занимать существенное время, скажем, 3-5 минут. второй шаг - отправка этого отчета в почту клиента.
то есть, "легкие" функции реализованы непосредственно - кнопку нажал - страница с результатом отобразилась, "тяжелые" функции реализованы запуском задания - кнопку нажал - сообщение отобразилось, результаты придут по почте.
P.S. Я покоцал код, думаю, понятно из каких соображений))) P.P.S. Надо иметь в виду что WWW работает в OMVS, так что CGI-BIN (REXX процедура выше) выполняется в OMVS
Сообщение отредактировал Gregory - Ср, 22.08.2012, 12:58
Отлично! Пока судьба находится в тумане - просто буду иметь ввиду. Как что прояснится - буду знать, к кому обращаться
ЗЫЖ Вообще-то у заказчика мечта - уйти от мэйнфрейма... При наличии 40% загрузки на тестовой машине в течение часов с продолжительными пиками до 90-100%, представляю, что творится на производственной. Так что интересно, что из этого получится. Но если намерения серьёзные, то OMVS не подойдёт.