02a - SQL

Up and down

Last Updated on 30 Novembre 2019 by Roberto De Pedrini

I suggerimenti di MarkOne – n. 4

Ti svelo l’IPL con SQL

Quando si è spento e acceso l’ultima volta il nostro IBM i? E quanto tempo ha impiegato per spegnersi ed accendersi?

In questo articolo vi suggerisco una semplice API e alcune istruzioni SQL pronte all’uso per estrarre dal sistema informazioni relative all’ultima operazione di spegnimento e accensione di IBM i.

Queste informazioni sono contenute in vari “angoli” del nostro sistema operativo (valori di sistema, messaggi dell’operatore di sistema, history log, …). Con poche istruzioni SQL le visualizziamo tutte insieme.

Consiglio (non solo in questo caso, ma in linea generale) di eseguire le istruzioni dal un client SQL “grafico”. Tutti abbiamo sicuramente a disposizione Esegui script SQL contenuto in IBM Access Client Solutions o IBM i Access. Oppure esistono tanti altri client SQL java-based (p.es. Squirrel SQL client, DBeaver, …).

ATTENZIONE! Le seguenti restrizioni si applicano alle istruzioni SQL scritte di seguito:

  • le istruzioni sono testate su IBM i 7.3 TR6 e IBM i 7.3 TR7
  • la funzione di tabella SPOOLED_FILE_DATA richiede IBM i 7.3 TR6
  • la funzione di tabella HISTORY_LOG_INFO richiede IBM i 7.3 TR1 o 7.2 TR5
  • la funzione di tabella JOB_INFO richiede IBM i 7.2 TR3
  • le CTE (clausola with) richiedono V5R4
  • la vista SYSTEM_VALUE_INFO richiede IBM i 7.1
  • la vista SCHEDULED_JOB_INFO richiede IBM i 7.2
  • l’API QWCCRTEC richiede IBM i 6.1

Innanzitutto eseguiamo l’API QWCCRTEC che produce uno spool QPSRVDMP con le informazioni dettagliate sulle varie fasi dello spegnimento e dell’accensione del sistema IBM i.

-->> informazioni sui passi di esecuzione dell'ultimo IPL
 -- N.B. da IBM i 7.1 non è più necessario specificare il secondo parametro con la lunghezza della stringa del comando da eseguire
 call qcmdexc('CALL QWCCRTEC');

Sempre nella stessa sessione di Esegui script SQL eseguiamo le seguenti 3 query.
ATTENZIONE: la funzione di tabella SPOOLED_FILE_DATA richiede IBM i 7.3 TR6. Se si vuole eseguire queste istruzioni su versioni precedenti bisogna togliere le parti di istruzione che usano tale funzione.

-->> Ultimo spegnimento
 with
  -- valore di sistema QABNORMSW
  SV_QABNORMSW as
  (select case when CURRENT_CHARACTER_VALUE = '1' then 'anomalo' else 'normale' end as SYSVAL
     from SYSTEM_VALUE_INFO
     where SYSTEM_VALUE_NAME = 'QABNORMSW'),
  -- estrazione orario inizio PWRDWNSYS dallo spool di QWCCRTEC
  PWRDOWN_START as
   (select timestamp_format(substr(SPOOLED_DATA, 103, 17), 'MM/DD/YY HH24:MI:SS', 0) as PDSTART
      from table(SYSTOOLS/SPOOLED_FILE_DATA('', 'QPSRVDMP'))      where ucase(substr(SPOOLED_DATA, 87, 11)) = 'XPF PWRDWN'),
  -- estrazione orario fine PWRDWNSYS dallo spool di QWCCRTEC
  PWRDOWN_END as
   (select timestamp_format(substr(SPOOLED_DATA, 103, 17), 'MM/DD/YY HH24:MI:SS', 0) as PDEND
      from table(SYSTOOLS/SPOOLED_FILE_DATA('', 'QPSRVDMP'))      where ucase(substr(SPOOLED_DATA, 87, 11)) = 'END PWRDWN'),
  -- estrazione messaggio CPI0995 (immissione PWRDWNSYS) da history log (DSPLOG)
  HSTLOG_CPI0995 as
   (select timestamp(MESSAGE_TIMESTAMP, 0) as M1TIME,
           trim(substr(MESSAGE_SECOND_LEVEL_TEXT, locate_in_string(MESSAGE_SECOND_LEVEL_TEXT, '. . . :', 1)+8)) as M1TEXT
      from table(HISTORY_LOG_INFO((select PDSTART - 1 hours from PWRDOWN_START),
                                  (select PDSTART + 1 hours from PWRDOWN_START))) as HL
      where MESSAGE_ID = 'CPI0995'
      order by MESSAGE_TIMESTAMP desc
      fetch first 1 rows only)
  -- query finale
  select
      SYSVAL as "Stato spegnimento",
      M1TIME as "Immissione PWRDWNSYS", PDSTART as "Inizio spegnimento", PDEND as "Fine spegnimento",
      M1TEXT as "Dettagli PWRDWNSYS"
   from SV_QABNORMSW left join PWRDOWN_START on 1=1 left join PWRDOWN_END on 1=1 left join HSTLOG_CPI0995 on 1=1;

Se lo spegnimento era andato a buon fine si otterrà un risultato simile a:

oppure se lo spegnimento si è concluso in modo anomalo:

Uno spegnimento anomalo p.es. potrebbe verificarsi se si esegue il comando PWRDWNSYS *IMMED e per qualche anomalia presente nel sistema il processo di spegnimento non termina prima del numero di secondi specificato nel valore di sistema QPWRDWNLMT oppure per una caduta di alimentazione non protetta da UPS, ecc.

L’istruzione successiva invece ci mostra i dettagli dell’ultima accensione del nostro sistema IBM i:

-->> Ultima accensione:
 with
  -- valore di sistema QIPLSTS
  SV_QIPLSTS as
  (select case CURRENT_CHARACTER_VALUE
           when '0' then 'pannello operatore'
           when '1' then 'automatico dopo ripristino alimentazione'
           when '2' then 'riavvio'
           when '3' then 'ora prestabilita'
           when '4' then 'remoto'
           else 'N/A' end as IPLSTS
     from SYSTEM_VALUE_INFO
     where SYSTEM_VALUE_NAME = 'QIPLSTS'),
  -- valore di sistema QIPLTYPE
  SV_QIPLTYPE as
  (select case CURRENT_CHARACTER_VALUE
           when '0' then 'non presidiato'
           when '1' then 'presidiato con DST'
           when '2' then 'presidiato (debug)'
           else 'N/A' end as IPLTYPE
     from SYSTEM_VALUE_INFO
     where SYSTEM_VALUE_NAME = 'QIPLTYPE'),
  -- estrazione orario inizio IPL dallo spool di QWCCRTEC
  IPL_START as
  (select timestamp_format(substr(SPOOLED_DATA, 103, 17), 'MM/DD/YY HH24:MI:SS', 0) as ISTART
     from table(SYSTOOLS/SPOOLED_FILE_DATA('', 'QPSRVDMP'))     where ucase(substr(SPOOLED_DATA, 87, 8)) = 'XPF IPL'
     fetch first 1 rows only -- solo il primo rek. In caso di IPL con applicazione PTF possono esserci due record consecutivi XPF IPL  ),  -- estrazione orario fine IPL dallo spool di QWCCRTEC  IPL_END as  (select timestamp_format(substr(SPOOLED_DATA, 103, 17), 'MM/DD/YY HH24:MI:SS', 0) as IEND     from table(SYSTOOLS/SPOOLED_FILE_DATA('', 'QPSRVDMP'))
     where ucase(substr(SPOOLED_DATA, 87, 11)) = 'END OF IPL'),  -- orario avvio job SCPF (Start Control Program Function)  SCPF_START as  (select JOB_ENTERED_SYSTEM_TIME as SCPFSTART     from table(JOB_INFO(JOB_STATUS_FILTER => 'ACTIVE', JOB_USER_FILTER   => 'QSYS')) as Job
     where JOB_NAME = '000000/QSYS/SCPF'),
  -- messaggio operatore sistema con informazioni su area IPL
  --   (il messaggio potrebbe essere stato rimosso quindi è meglio estrarre questa informazione dall'history log)
 -- QSYSOPR_AREAIPL as
 -- (select trim(MESSAGE_TEXT) as AREAIPL, timestamp(MESSAGE_TIMESTAMP, 0) as AREAIPL_TIME
 --    from QSYS2/MESSAGE_QUEUE_INFO
 --    where MESSAGE_QUEUE_NAME = 'QSYSOPR' and MESSAGE_ID = 'CPI0C04'),
  -- estrazione messaggi da history log (DSPLOG)
  HSTLOG as
   (select MESSAGE_ID, timestamp(MESSAGE_TIMESTAMP, 0) as M1TIME,
           MESSAGE_TEXT as M1TEXT1, MESSAGE_SECOND_LEVEL_TEXT as M1TEXT2
      from table(HISTORY_LOG_INFO((select ISTART - 1 hours from IPL_START),
                                  (select IEND + 1 hours from IPL_END))) as HL
      where MESSAGE_ID in ('CPI0C04', 'CPF0998', 'CPI091D')),
  -- estrazione messaggio CPI0C04 da history log: area IPL
  HSTLOG_CPI0C04 as
  (select trim(M1TEXT1) as M1TEXT1
     from HSTLOG
     where MESSAGE_ID = 'CPI0C04'
    order by M1TIME desc
    fetch first 1 rows only),
  -- estrazione messaggio CPF0998 da history log: chiusura anomala
  HSTLOG_CPF0998 as
  (select M1TEXT1
     from HSTLOG
     where MESSAGE_ID = 'CPF0998'
    order by M1TIME desc
    fetch first 1 rows only),
  -- estrazione messaggio CPI091D da history log: causa chiusura anomala
  HSTLOG_CPI091D as
  (select substr(M1TEXT1, locate_in_string(M1TEXT1, 'codice causa', 1)+13, 1) as CODICE,
           substr(M1TEXT2, 
                  locate_in_string(M1TEXT2, '&P ' concat substr(M1TEXT1, locate_in_string(M1TEXT1, 'codice causa', 1)+13, 1), 1)+7,
                  (locate_in_string(M1TEXT2, '&P ', locate_in_string(M1TEXT2, '&P ' concat substr(M1TEXT1, locate_in_string(M1TEXT1, 'codice causa', 1)+13, 1), 1)+1)-1) - 
                   (locate_in_string(M1TEXT2, '&P ' concat substr(M1TEXT1, locate_in_string(M1TEXT1, 'codice causa', 1)+13, 1), 1)+7)
                 ) 
            as DESCRIZIONE
     from HSTLOG
     where MESSAGE_ID = 'CPI091D'
    order by M1TIME desc
    fetch first 1 rows only)    
  -- query finale
  select IPLSTS as "Tipo di IPL eseguito", IPLTYPE as "Tipo IPL da eseguire",
         ISTART as "Inizio accensione", 
         SCPFSTART as "Data/Ora avvio Start Control Program Function",
         IEND as "Fine accensione",
         HSTLOG_CPI0C04.M1TEXT1 as "Area IPL",
         case when HSTLOG_CPF0998.M1TEXT1 is null then 'No' else 'Sì' end as "IPL dopo chiusura anomala",
         HSTLOG_CPI091D.CODICE concat ' - ' concat HSTLOG_CPI091D.DESCRIZIONE as "Causa chiusura anomala"
    from SV_QIPLSTS, SV_QIPLTYPE, IPL_START, IPL_END, SCPF_START
      left join HSTLOG_CPI0C04 on 1=1
      left join HSTLOG_CPF0998 on 1=1
      left join HSTLOG_CPI091D on 1=1;

Le informazioni di accensione potrebbero essere simili a:

Dopo uno spegnimento anomalo le informazioni della successiva accensione potrebbero essere simili a:

Infine con questa ultima istruzione visualizziamo la data/ora pianificata per la prossima accensione pianificata o dal menu POWER opz. 2 oppure tramite un job schedulato che esegue un PWRDWNSYS con parametro RESTART(*YES).

-->> Prossima accensione pianificata
   -- accensione programmata in menu POWER
 select 'Menu POWER' as "Tipo",
         timestamp_format(substr(trim(CURRENT_CHARACTER_VALUE), 2), 'YYMMDDHH24MISS', 0) as "Data/ora prossima accensione"
   from SYSTEM_VALUE_INFO
   where SYSTEM_VALUE_NAME = 'QIPLDATTIM'
     and CURRENT_CHARACTER_VALUE <> 'NONE'
union all
   -- accensione schedulata con comando PWRDWNSYS … RESTART(YES)
 select 'Job schedulato' as "Tipo", 
        timestamp_format(NEXT_SUBMISSION_DATE concat ' ' concat SCHEDULED_TIME, 'YYYY-MM-DD HH24:MI:SS', 0) as "Data/ora prossima accensione"
   from SCHEDULED_JOB_INFO as JS
   where ucase(COMMAND_STRING) like '%PWRDWNSYS%RESTART(*YES)%'
     and STATUS = 'SCHEDULED'
 order by 2;

Se la query non restituisce nessun record significa che non è stata pianificata nessuna accensione del sistema IBM i.

Se tramite il menu POWER è stato impostato l’accensione in data 2/12/2019 alle 1.30 si otterrà

Se invece si imposta un riavvio tramite un job schedulato per la data del 25/12/2025 alle 23.00 si otterrà:

Scarica lo script completo da https://gist.github.com/mk1tools/575e3ac809736e01b724928fc2c48597

Bibliografia

Queste e molte altre istruzioni SQL prêt-à-porter sul blog MarkOneTools https://www.markonetools.it/sql-pret-a-porter/

Related Posts
DB2 for i SQL – Stringhe – POSSTR-LOCATE-LOCATE_IN_STRING (IT)

Introduzione Spesso, nelle nostre applicazioni, abbiamo la necessità di lavorare con le stringhe di testo e l'SQL del DB2 può Read more

DB2 for i & SQL – FAQ & Howto (Part. 1) (IT)

Database DB2 e SQL ... forse lo strumento più potente e completo che abbiamo sulla piattaforma IBM i: ecco una Read more

Annuncio IBM i 7.4

Arriva direttamente con l'uovo di Pasqua questo annuncio IBM per le novità della versione IBM i 7.4, versione iNext secondo Read more

Generated Always Columns – Approfondimenti (IT)

Introduzione "Generated Always Column": sono colonne, campi, di una tabella il cui contenuto è controllato direttamente dal sistema ... e Read more

About author

mentore IBM i IBM Champion 2021 for Power Systems

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *