La settimana scorsa (beh, era la settimana scorsa quando ho iniziato a scrivere questo articolo) abbiamo avuto un problema al CAC in cui qualcuno voleva scrivere una macro di comando che eseguiva telnet per accedere a un sistema ed eseguire alcuni comandi, ad esempio la macro di comando test.cm accede a un host remoto ed esegue la macro di comando foo.cm.
&attach_input
telnet 192.168.77.128
password
foo.cm
|
|
Figura 1 – Macro del comando telnet test.cm |
display_line display_system_usage
display_system_usage
display_line netstat -statistics -protocol tcp
netstat -statistics
display_line analyze_system -request_line 'stcp_meters -all -long' -quit
analyze_system -request_line 'stcp_meters' -quit
|
|
Figura 2 – foo.cm |
Purtroppo Telnet non è progettato per essere eseguito all'interno di una macro di comando e quindi non funziona.
test
telnet: errore irreversibile - tcgetattr non riuscito
Errore alla riga 3 di test.
command_processor: Oggetto non trovato. password. Nella macro di comando
%azvos#m17_mas>SysAdmin>Noah_Davids>test.cm
|
|
Figura 3 – L'esecuzione di test.cm non va a buon fine |
Esistono tuttavia diversi modi per effettuare l'accesso automatico a un host remoto e eseguire successivamente un comando.
send_cmds.c:
Qualche tempo fa ho scritto un programma che si connette a un server Telnet, invia stringhe e analizza l'output. Il linguaggio di scripting è semplice, ma per operazioni di base funziona bene. Il codice sorgente con esempi più dettagliati è disponibile qui
Lo script consiste fondamentalmente in una stringa di invio seguita da una stringa di attesa. Lo script passa alla riga successiva quando viene rilevata la stringa di attesa; come ho detto, è molto semplice. Lo script ha degli argomenti; nella figura 4 utilizzo arg0 per la password, in modo che la mia password non venga memorizzata nello script. L'esecuzione dello script è mostrata nella figura 5. Ho troncato l'output di ciascun comando per risparmiare spazio. Noterete che i caratteri non di controllo delle stringhe di posizionamento dei caratteri vengono visualizzati finché non imposto il tipo di terminale su ASCII.
//login
/login nd/Password?
/arg0/ready
/set_terminal_parameters -terminal_type ascii -pause_lines 0/ready
/foo.cm/ready
/quit/quit
|
|
Figura 4 – Script `send_cmds` per effettuare l'accesso ed eseguire la macro del comando `foo` |
send_cmds -IPAddress 192.168.77.128 -InputFilePath test.send_cmds -no_Verbose -a
+rg0 password
SISTEMA DI PROVA PHOENIX CAC VOS (%phx_vos#m16)
*** Per l'avvio su una versione VOS diversa, vedere ***
*** >Overseer>COMMON>cfg>reconfig_instructions ***
OpenVOS versione 17.1.0ax, modulo %phx_vos#m16
Effettuare il login 08:15:01
login nd
Password?
Noah_Davids.CAC ha effettuato l'accesso su %phx_vos#m16 alle 13-04-21 08:15:01 mst.
[f[J[?7l[20l=[1m[1;24r[f[J[J[24;80f
[0;1mpronto 08:15:01
[0mset_terminal_parameters -terminal_type ascii -pause_lines 0
[1mset_terminal_parameters -terminal_type ascii -pause_lines 0
pronto 08:15:01
foo.cm
display_system_usage
Statistiche di utilizzo per il modulo %phx_vos#m16, G94330, OpenVOS Release 17.1.0ax
Tutte le 762,6 ore (31,7 giorni) attive.
----CPU----- Ultimo minuto Ultimi 5 minuti Ultima ora Tempo totale di attività
. . . . .
Tempo interno 0,00 0,1% 0,02 0,1% 0,23 0,1% 191,65 0,1%
netstat -statistics
tcp:
. . . .
201766 tcpOutRsts
analyze_system -request_line stcp_meters -all -long -quit
OpenVOS Release 17.1.0ax, analyze_system Release 17.1.0ax
Il processo corrente è 884, ptep 8D3E6000, Noah_Davids.CAC
stcp_meters %phx_vos#m16 762:36:19 21-04-13 08:15:02
. . . .
bufdat eseguito 678 (media 0,0002/sec)
pronto 08:15:02
pronto 08:15:03
|
|
Figura 5 – Esecuzione di send_cmds |
aspettarsi:
Nella libreria gnu_library è presente un programma chiamato expect. La sintassi di uno script expect può essere molto complessa; consente infatti di effettuare ramificazioni in base a diverse stringhe di ritorno, permettendo così di gestire gli errori in modo intelligente invece di limitarsi a un timeout. È possibile trovare esempi sul web, basta cercare “esempi di script expect”. Vi presenterò uno script semplice che si limita ad effettuare il login ed eseguire la macro foo.cm. Si noti che nelle prime versioni di gnu_tools erano presenti alcuni bug (motivo per cui ho scritto send_cmds), ma a partire dalla versione 3.4.0a non dovrebbero esserci problemi. Anche se non lo mostro, expect può anche utilizzare argomenti, quindi la password non deve necessariamente far parte dello script oppure lo script può richiedere l'inserimento della password. Anche in questo caso ho troncato l'output del comando dallo script e potete vedere che i caratteri non di controllo delle stringhe di posizionamento dei caratteri vengono visualizzati finché non imposto il tipo di terminale su ascii. Expect, tuttavia, filtra la stringa in modo diverso, quindi non vengono mostrati tutti i caratteri.
avvia "telnet"
aspetta "telnet>"
invia "open 192.168.77.128r"
aspetta "login"
invia "login ndr"
aspetta "Password"
invia "passwordr"
aspetta "ready"
invia "set_terminal_parameters -terminal_type ascii -pause_lines 0r"
aspetta "ready"
invia "foo.cmr"
aspetta "ready"
|
|
Figura 6 – Lo script dovrebbe effettuare l'accesso ed eseguire la macro del comando foo |
>bin>expect test.expect\
spawn telnet\
telnet> open 192.168.77.128\
Tentativo in corso...\
Connesso a 192.168.77.128.\
Il carattere di escape è '^]'.
SISTEMA DI PROVA PHOENIX CAC VOS (%phx_vos#m16)
*** Per l'avvio su una versione VOS diversa, vedere ***
*** >Overseer>COMMON>cfg>reconfig_instructions ***
OpenVOS versione 17.1.0ax, modulo %phx_vos#m16
Effettua il login 08:51:28
login nd
Password?
Noah_Davids.CAC ha effettuato l'accesso su %phx_vos#m16 alle 08:51:28 mst del 21-04-13.
fJ?7l20l
0;1mpronto 08:51:28
1mset_terminal_parameters -terminal_type ascii -pause_lines 0
pronto 08:51:28
foo.cm
display_system_usage
Statistiche di utilizzo per il modulo %phx_vos#m16, G94330, OpenVOS Release 17.1.0ax
Totale 763,2 ore (31,8 giorni) di attività.
----CPU----- Ultimo minuto Ultimi 5 minuti Ultima ora Tempo di attività totale
. . . .
Tempo interno 0,00 0,1% 0,02 0,1% 0,24 0,1% 191,80 0,1%
netstat -statistics
tcp:
. . . .
201926 tcpOutRsts
analyze_system -request_line stcp_meters -all -long -quit
OpenVOS Release 17.1.0ax, analyze_system Release 17.1.0ax
Il processo corrente è 895, ptep 8D2E1200, Noah_Davids.CAC
stcp_meters %phx_vos#m16 763:12:46 21-04-13 08:51:29
. . . .
bufdat eseguito 678 (media 0,0002/sec)
pronto 08:51:29
pronto 08:51:29
|
|
Figura 7 – Esecuzione dello script expect |
SSH:
Infine, è possibile utilizzare SSH per eseguire un comando su un sistema remoto. Se è stata configurata anche l'autenticazione tramite chiave pubblica, al momento dell'esecuzione non verrà richiesta la password.
L'uso di SSH presenta alcune particolarità interessanti. Innanzitutto, le abbreviazioni non funzionano: non provare a eseguire «dps», ma usa «display_print_status».
ssh [email protected] dbs
sh: dbs: comando non trovato
pronto 12:26:25
|
|
Figura 8 – L'uso di SSH per eseguire in remoto un comando abbreviato non funziona |
ssh [email protected] display_batch_status
Code batch per %phx_vos#m16
CODA STATO MAX LAVORI IN CORSO D'ESECUZIONE
normale in esecuzione 5
pronto 12:26:43
|
|
Figura 9 – L'esecuzione remota di un comando tramite SSH funziona |
In secondo luogo, l'esecuzione diretta di una macro di comando non funziona; si noti che non viene visualizzato alcun risultato e sembra che sia stato elaborato solo il primo comando della macro.
ssh [email protected] 'foo.cm'
display_system_usage
pronto 12:08:40
|
|
Figura 10 – L'uso di SSH per eseguire in remoto una macro di comando non sempre funziona |
Bisogna invece eseguire il comando della shell e specificare la macro di comando come argomento.
ssh [email protected] '/bin/sh foo.cm'
display_system_usage
Statistiche di utilizzo per il modulo %phx_vos#m16, G94330, OpenVOS versione 17.1.0ax
Totale: 766,5 ore (31,9 giorni) di attività.
----CPU----- Ultimo minuto Ultimi 5 minuti Ultima ora Tempo di attività totale
Minuti CPU 0,02 0,5% 0,09 0,4% 0,91 0,4% 724,76 0,4%
. . . .
Tempo interno 0,00 0,1% 0,02 0,1% 0,23 0,1% 192,57 0,1%
netstat -statistics
tcp:
. . . .
202796 tcpOutRsts
analyze_system -request_line stcp_meters -all -long -quit
OpenVOS Release 17.1.0ax, analyze_system Release 17.1.0ax
Il processo corrente è 922, ptep 8D3C2780, Noah_Davids.CAC
stcp_meters %phx_vos#m16 766:30:14 21-04-13 12:08:57
. . . .
bufdat eseguito 678 (media 0,0002/sec)
pronto 12:08:59
|
|
Figura 11 – Utilizzo di SSH per eseguire in remoto una macro di comando come script di shell |
Le macro complesse non funzioneranno. Ad esempio, ogni riga della macro di comando viene eseguita in un processo separato, quindi le macro che utilizzano la variabile `process_dir` per memorizzare i risultati intermedi non funzioneranno. Si noti che ogni chiamata alla funzione `analyze_system` restituisce un numero di processo diverso.
ssh [email protected] '/bin/sh foo3.cm'
%phx_vos#m16_mas>SysAdmin>Noah_Davids>foo3.cm 21-04-13 12:52:20 mst
display foo3.cm
display_line
analyze_system -request_line '' -quit
analyze_system -request_line '' -quit
analyze_system -request_line '' -quit
OpenVOS versione 17.1.0ax, analyze_system versione 17.1.0ax
Il processo corrente è 1028, ptep 8D3C3000, Noah_Davids.CAC
OpenVOS versione 17.1.0ax, analyze_system versione 17.1.0ax
Il processo corrente è 1029, ptep 8D3C3000, Noah_Davids.CAC
OpenVOS versione 17.1.0ax, analyze_system versione 17.1.0ax
Il processo corrente è 1030, ptep 8D3C3000, Noah_Davids.CAC
pronto 12:52:21
|
|
Figura 12 – Ogni comando della macro viene eseguito come processo separato |
L'uso di macro di comando con variabili in stile VOS genererà errori di sintassi, poiché la shell non le riconosce. La macro di comando foo3.cm visualizza se stessa e poi conta fino a 9. Il comando display viene eseguito e "&set" genera un errore di sintassi.
ssh [email protected] '/bin/sh foo3.cm'
%phx_vos#m16_mas>SysAdmin>Noah_Davids>foo3.cm 13-04-22 07:33:18 mst
display foo3.cm
&set COUNT 1
&label again
display_line &COUNT&
&set COUNT (calc &COUNT& + 1)
&if &COUNT& < 10 &then &goto again
foo3.cm: line 2: syntax error near unexpected token `&s'
foo3.cm: line 2: `&set COUNT 1'
ready 07:33:18
|
|
Figura 13 – Le macro di comando con variabili in stile VOS non funzionano |
Ma l'uso delle variabili di shell funzionerà. Ciò, ovviamente, potrebbe richiedere una riscrittura approfondita delle macro esistenti. Ecco un esempio della stessa macro sotto forma di script di shell.
ssh [email protected] '/bin/sh foo3u'
cat foo3u
count=1
while [[ $count -le 9 ]]
do
echo "$count"
(( count++ ))
done
1
2
3
4
5
6
7
8
9
pronto 07:44:41
|
|
Figura 14 – Lo script Shell con variabili di tipo shell funziona |
Tuttavia, è possibile eseguire la macro di comando in stile VOS come processo avviato e quindi visualizzare il file di output generato. La macro start_foo3.cm esegue start_process, attende che il processo si concluda e quindi visualizza il file di output senza intestazione. Ho modificato il file foo3.cm per disattivare le righe di comando e di macro, nonché il prompt "ready", in modo da riprodurre più fedelmente l'output di una macro di comando eseguita in modo interattivo.
avvia_processo foo3.cm -wait
visualizza foo3.out -no_header
|
|
Figura 15 – Macro di comando per eseguire foo3.cm come processo avviato |
Ad eccezione dell'intestazione di accesso e del nome della macro di comando nelle prime due righe, nonché della riga «Process finished» alla fine, i risultati sono gli stessi che si otterrebbero eseguendo la macro dalla riga di comando VOS.
ssh [email protected] '/bin/sh start_foo3.cm'
Noah_Davids.CAC logged in on %phx_vos#m16 at 13-04-22 10:45:23 mst.
foo3.cm
%phx_vos#m16_mas>SysAdmin>Noah_Davids>foo3.cm 13-04-22 10:45:23 mst
&echo no_input_lines no_command_lines no_macro_lines
set_ready -format off
display foo3.cm
&set COUNT 1
&label again
display_line &COUNT&
&set COUNT (calc &COUNT& + 1)
&if &COUNT& < 10 &then &goto again
1
2
3
4
5
6
7
8
9
Process finished.
ready 10:45:25
|
|
Figura 16 – Risultati dell'esecuzione di foo.cm in un processo avviato |
Come puoi vedere, quindi, anche se non è possibile utilizzare Telnet, esistono altri modi per effettuare l'accesso in modo automatico ed eseguire comandi.
