Практический пример применения SMF для контроля удаления наборов данных
Постановка задачи. Необходимо в человекочитаемом виде
протоколировать случаи удаления наборов данных в файловом хранилище на
мэйнфрейме. Нужно записывать в некий протокол имя набора данных, время
и дату его удаления, а также имя адресного пространства, которое выдало
команду на удаление. При этом интересны случаи удаление только наборов,
имя которых начинается с "ARCHIVE.".
Общие замечания. На случай,
если кто-то совсем не работал с SMF, я напомню некоторые общие
положения. SMF - один из стрейших и самых общих механизмов мониторинга
событий в ОС. Смысл его состоит в том, что в результате всевозможных
событий в системе порождаются и записываются сначала в память, а потом
и в специальные наборы данных записи различных форматов. Записи,
порождаемые разными событиями, имеют различный формат - количество
полей, содержимое информации в полях, длина. Чтобы отличать записи одну
от другой, каждая запись имеет дескриптор, именуемый типом. он
находится во втором байте каждой записи. Типов записей, а,
соотвественно, и дескрипторов - много, так как и регистрируемых событий
тоже много. Например, случай удаления набора данных описывается
записями регистрации типа 17, а RMF использует записи нескольких типов
- с 70 по 79. Вообще этих типов записей много - сейчас уже более 120
(для zOS 1.8). Количество типов будет расти, я так думаю. Сами записи -
шестнадцатеричные последовательности. Для того, чтобы к ним добраться,
саписи из наборов данных SMF надо выгрузить в последовательный набор
данных.
Решение задачи. Задача решалась так.
Каждую
ночь, в 00.01 минуту происходило переключение на свободный SMF-набор,
чтобы освободить остальные. Делалось это командой SWITCH SMF с
операторской консоли, или из авторизованного задания.
Осуществлялась выгрузка наборов данных SMF в последовательный набор данных. Приблизительно вот так -
//**************************************************************** //* JOB TO DUMP SMF RECORDS //* VERIFY THE DUMPIN AND DUMPOUT DDS //**************************************************************** //DMPSMF1 EXEC PGM=IFASMFDP,REGION=4096K //SYSPRINT DD SYSOUT=A //SMFIN DD DISP=OLD,DSN=SYS1.MAN1 <--------- входной набор //SMFOUT DD DISP=SHR,DSN=Z18LCL.RMFBASE <--------- выходной набор //SYSIN DD * INDD(SMFIN,OPTIONS(ALL)) OUTDD(SMFOUT,TYPE(000:255)) //****************************************************************
теперь
у нас есть последовательный файл с записями SMF всех типов. В принципе,
можно выгружать только нужный тип записей, но у нас несколько заданий
последовательно вынимают требуемую информацию, так что я выгружаю все.
Теперь
нужно отобрать только нужные записи, отсортировать их, и красиво
показать. Раньше я писал бы свою программку для отбора, потом
сортировал бы сортировкой, потом бы формировал красивый протокольчик.
Но у нас есть DFSORT - программа, которая может практически все. В
результате я получаю требуемый протокол так -
Как
все работает ? Смотрим на DD TOOLIN, там лежит последовательность
действий для сортировки. Разберем подробнее, что там есть. Всего в этом
кусочке три оператора - два оператора SORT и один оператор DISPLAY.
Сначала первым оператором SORT из входного НД (имя DD - SMFRAW, имя НД
- Z18LCL.RMFBASE), полученного в результате выгрузки из SMF-наборов,
отбираются записи нужного типа и укладываются во временный набор (имя
DD - SMFSEL1, имя НД выбирает система). Это делается на основе
содержимого SMFICNTL, где говорится как сортировать отобранные на
основе оператора INCLUDE записи. Потом вторым оператором SORT из
входного НД (имя DD - SMFSEL1, имя НД выбирает система) отбираются
записи, где в поле с именем набода данных первые 7 байт соответствуют
"ARCHIVE", но при этом наборы с именем "ARCHIVE.PKES" нам не нужны.
Результаты уклдываются во временный набор (имя DD - SMFSEL2, имя НД
выбирает система). Это делается на основе содержимого SMFАCNTL, где
говорится как сортировать отобранные на основе оператора INCLUDE
записи. А потом - оператор DISPLAY представляет результат в символьной
форме, без заголовков, только те кусочки сортированных данных, которые
нужны. Выходит нечто вроде -
тут
видны дата и время удаления, имя адресного пространства, которое
удаляло (задание, пользователь, сервер), и имя удаленного набора. Я
этот протокол накапливаю, а потом, при необходимости, обрабатываю
другими программами или просто смотрю глазами.
Категория: Примеры | Добавил: akost (10.10.2008)
| Автор: Костырко Александр
спасибо, пригодилось! но есть вопрос - как в DFSORT обрабатывать данные из SMF type 30 record, а именно, Identification section, Completion section и т.д.? Позиция этих секций в записи не постоянна, смещения на эти секции указываются в record header (SMF30IOF, SMF30TOF ...). Полдня читал DFSORT, ответа пока не нашел( Может быть, кто-то подскажет?
Ещё на СВТ есть утилитка DAF. Умеет как раз анализировать SMF записи и по заданным критериям выдёргивать. Несколько раз пригодилась для расследования жалоб пользователей, что их н.д. куда-то исчезают.
Reformat SMF records type 30 subtype 5 (job termintation) to fixed format. Specific SMF records should be preprocessed with IFASMFDP to improve performance and become RECFM=V data set.
*/ do forever "EXECIO 1 DISKR INPUT" if rc <> 0 then leave parse pull in parse var in , 2 SMF30RTY +1 11 SMF30SID +4 15 SMF30WID +4 19 SMF30STP +2 , 29 SMF30IOF +4 33 SMF30ILN +2 35 SMF30ION +2 43 SMF30UON +2 , 45 SMF30TOF +4 49 SMF30TLN +2 51 SMF30TON +2 53 SMF30COF +4 , 57 SMF30CLN +4 59 SMF30CON +2 67 SMF30AON +2 69 SMF30ROF +4 , 73 SMF30RLN +4 75 SMF30RON +2 77 SMF30POF +4 81 SMF30PLN +4 , 83 SMF30PON +2 85 SMF30OOF +4 91 SMF30OON +2 92 SMF30OLN +2 , 115 SMF30DRN +2 123 SMF30ARN +2 select when SMF30RTY <> '1E'x then iterate /* skip all except type 30 */ when SMF30STP <> '0005'x then iterate /* skip all except subtype 5 */ when SMF30WID = 'STC' then iterate /* skip starting tasks */ when SMF30AON''SMF30ARN''SMF30CON''SMF30DRN''SMF30OON''SMF30PON''SMF30RON''SMF30TON''SMF30UON = copies('0000'x,9) then iterate /* additional record */ otherwise nop end SMF30IOF = c2d(SMF30IOF) - 3 SMF30TOF = c2d(SMF30TOF) - 3 SMF30COF = c2d(SMF30COF) - 3 SMF30ROF = c2d(SMF30ROF) - 3 SMF30POF = c2d(SMF30POF) - 3 SMF30OOF = c2d(SMF30OOF) - 3 if (SMF30IOF > 0 & SMF30ION = '0001'x & SMF30ILN <> '0000'x) then do /* IDENTIFICATION SECTION */ SMF30JBN = substr(in,SMF30IOF,8) SMF30SIT = substr(in,SMF30IOF+56,4) SMF30STD = substr(in,SMF30IOF+60,4) SMF30USR = substr(in,SMF30IOF+80,20) SMF30RUD = substr(in,SMF30IOF+108,8) end if (SMF30POF > 0 & SMF30PON = '0001'x & SMF30PLN <> '0000'x) then do /* PERFORMANCE SECTION */ SMF30CSU = substr(in,SMF30POF+4,4) SMF30SRB = substr(in,SMF30POF+8,4) SMF30IO = substr(in,SMF30POF+12,4) end if (SMF30COF > 0 & SMF30CON = '0001'x & SMF30CLN <> '0000'x) then do /* PROCESSOR ACCOUNTING SECTION */ SMF30CPT = substr(in,SMF30COF+4,4) SMF30CPS = substr(in,SMF30COF+8,4) SMF30ICU = substr(in,SMF30COF+12,4) SMF30JVU = substr(in,SMF30COF+20,4) SMF30IVU = substr(in,SMF30COF+24,4) end if (SMF30TOF > 0 & SMF30TON = '0001'x & SMF30TLN <> '0000'x) then do /* COMPLETION SECTION */ SMF30SCC = substr(in,SMF30TOF,2) SMF30TME = substr(in,3,4) SMF30DTE = substr(in,7,4) end ELAPSED = d2c(c2d(SMF30TME)-c2d(SMF30SIT),4) out.1 = left(SMF30RUD,8) left(SMF30JBN,8) left(SMF30WID,8) , SMF30STD SMF30SIT SMF30DTE SMF30TME ELAPSED left(SMF30USR,20) , SMF30CSU SMF30SRB SMF30IO SMF30CPT SMF30CPS SMF30ICU , SMF30JVU SMF30IVU SMF30SCC "EXECIO 1 DISKW OUTPUT (STEM OUT." end "EXECIO 0 DISKR INPUT (FINIS" "EXECIO 0 DISKW OUTPUT (FINIS" exit 0
а вместо ICETOOL DISPLAY использовал DFSORT: SORT FIELDS=(1,8,CH,A) OUTREC FIELDS=(1,8,C';',10,8,C';',19,8,C';', 28,4,DT1,EDIT=('TTTT-TT-TT'),C';', 33,4,TM1,EDIT=('TT:TT:TT'),C';', 38,4,DT1,EDIT=('TTTT-TT-TT'),C';', 43,4,TM1,EDIT=('TT:TT:TT'),C';', 48,4,TM1,EDIT=('TT:TT:TT'))
в результате получаем CSV, который можно визуализировать в разные диаграммы с помощью excel или 123. DFSORT вместо ICETOOL DISPLAY использован чтобы убрать разбиение на страницы