Aller directement au contenu principal

La semaine dernière (enfin, c'était la semaine dernière quand j'ai commencé à rédiger cet article), nous avons reçu une demande au CAC : quelqu'un souhaitait créer une macro de commande qui lancerait une session Telnet pour se connecter à un système et y exécuter certaines commandes. Par exemple, la macro de commande test.cm se connecte à un hôte distant et exécute la macro de commande foo.cm.

&attach_input                                                                 
telnet 192.168.77.128
mot de passe
foo.cm

Figure 1 – Commande Telnet : macro 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

Figure 2 – foo.cm

 

Malheureusement, Telnet n'est pas conçu pour s'exécuter dans une macro de commande et l'opération échoue.

test                                                                          
telnet : erreur fatale - échec de tcgetattr
Erreur à la ligne 3 de test.
command_processor : Objet introuvable. password. Dans la macro de commande
     %azvos#m17_mas>SysAdmin>Noah_Davids>test.cm

Figure 3 – L'exécution du fichier test.cm échoue

 

Il existe toutefois plusieurs façons de se connecter automatiquement à un hôte distant puis d'y exécuter des commandes.

send_cmds.c :

J'ai écrit il y a quelque temps un programme qui établit une connexion avec un serveur Telnet, envoie des chaînes de caractères et analyse la sortie. Le langage de script est simple, mais il fonctionne très bien pour des tâches basiques. Vous trouverez le code source, accompagné d'exemples plus complets, ici

Le script consiste essentiellement en une chaîne d'envoi suivie d'une chaîne d'attente. Le script passe à la ligne suivante dès qu'il détecte la chaîne d'attente ; comme je l'ai dit, c'est très simple. Le script comporte des arguments ; dans la figure 4, j'utilise arg0 pour le mot de passe afin que celui-ci ne soit pas stocké dans le script. L'exécution du script est illustrée à la figure 5. J'ai tronqué la sortie de chaque commande pour gagner de la place. Vous remarquerez que les caractères non de contrôle des chaînes de positionnement de caractères s'affichent jusqu'à ce que je définisse le type de terminal sur ascii.

//login                                                                         
/login nd/Password?
/arg0/ready
/set_terminal_parameters -terminal_type ascii -pause_lines 0/ready
/foo.cm/ready
/quit/quit

Figure 4 – Script « send_cmds » permettant de se connecter et d'exécuter la macro de commande « foo »

send_cmds -IPAddress 192.168.77.128 -InputFilePath test.send_cmds -no_Verbose -a
+rg0 password

       SYSTÈME DE TEST PHOENIX CAC VOS (%phx_vos#m16)

   *** Pour démarrer sur une autre version de VOS, voir     ***
   *** >Overseer>COMMON>cfg>reconfig_instructions ***

OpenVOS version 17.1.0ax, module %phx_vos#m16
Veuillez vous connecter  08:15:01
login nd
Mot de passe ?
Noah_Davids.CAC s'est connecté sur %phx_vos#m16 le 21/04/2013 à 08:15:01 (heure normale des Rocheuses).
[f[J[?7l[20l=[1m[1;24r[f[J[J[24;80f
[0;1mPrêt  08:15:01
[0mset_terminal_parameters -terminal_type ascii -pause_lines 0
[1mset_terminal_parameters -terminal_type ascii -pause_lines 0

prêt  08:15:01
foo.cm
display_system_usage
Statistiques d'utilisation pour le module %phx_vos#m16, G94330, OpenVOS version 17.1.0ax
762,6 heures (31,7 jours) de fonctionnement total.
----CPU-----         Dernière minute     5 dernières minutes       Dernière heure      Temps de fonctionnement total
. . . . .
Temps interne           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 version 17.1.0ax, analyze_system version 17.1.0ax
Le processus actuel est 884, ptep 8D3E6000, Noah_Davids.CAC

stcp_meters   %phx_vos#m16                762:36:19     21/04/13 08:15:02
 . . . .
   bufdat exécuté                             678 (moyenne 0,0002/sec)

prêt  08:15:02
prêt  08:15:03

Figure 5 – Exécution de send_cmds

 

s'attendre à :

La bibliothèque gnu_library contient un programme appelé expect. La syntaxe d'un script expect peut être très complexe ; elle permet d'effectuer des branchements en fonction de différentes chaînes de retour, ce qui vous permet de gérer les erreurs de manière intelligente au lieu de simplement attendre l'expiration du délai. Vous pouvez trouver des exemples sur Internet ; il suffit de rechercher « exemples de scripts expect ». Je vais vous présenter un script simple qui se contente de se connecter et d'exécuter la macro foo.cm. Notez qu'il y avait quelques bogues dans les premières versions de gnu_tools (c'est pourquoi j'ai écrit send_cmds), mais à partir de la version 3.4.0a, tout devrait fonctionner correctement. Bien que je ne le montre pas ici, expect peut également utiliser des arguments ; le mot de passe n'a donc pas besoin de faire partie du script, ou bien le script peut vous demander de le saisir. Une fois encore, j'ai tronqué la sortie de la commande du script et vous pouvez voir que les caractères non de contrôle des chaînes de positionnement de caractères s'affichent jusqu'à ce que je définisse le type de terminal sur ascii. Expect filtre toutefois la chaîne différemment, de sorte que tous les caractères ne sont pas affichés.

lancer "telnet"                                                                
attendre "telnet>"
envoyer "open 192.168.77.128r"
attendre "login"
envoyer "login ndr"
attendre "Password"
envoyer "passwordr"
attendre "ready"
envoyer "set_terminal_parameters -terminal_type ascii -pause_lines 0r"
attendre "ready"
envoyer "foo.cmr"
attendre "ready"

Figure 6 – Le script « expect » doit se connecter et exécuter la macro de commande « foo »

>bin>expect test.expect\
spawn telnet\
telnet> open 192.168.77.128\
Essai en cours...\
Connecté à 192.168.77.128.\
Le caractère d'échappement est « ^] ».


       SYSTÈME DE TEST PHOENIX CAC VOS (%phx_vos#m16)

   *** Pour démarrer sur une autre version de VOS, voir     ***
   *** >Overseer>COMMON>cfg>reconfig_instructions ***

OpenVOS version 17.1.0ax, module %phx_vos#m16
Veuillez vous connecter  08:51:28
login nd
Mot de passe ?

Noah_Davids.CAC s'est connecté sur %phx_vos#m16 le 21/04/13 à 08:51:28 mst.
fJ?7l20l
0;1mPrêt  08:51:28
1mset_terminal_parameters -terminal_type ascii -pause_lines 0
prêt  08:51:28
foo.cm
display_system_usage
Statistiques d'utilisation pour le module %phx_vos#m16, G94330, OpenVOS version 17.1.0ax
763,2 heures (31,8 jours) de fonctionnement.

----CPU-----         Dernière minute     5 dernières minutes       Dernière heure      Temps de fonctionnement total
. . . .
Temps interne           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 version 17.1.0ax, analyze_system version 17.1.0ax
Le processus actuel est 895, ptep 8D2E1200, Noah_Davids.CAC

stcp_meters   %phx_vos#m16                763:12:46     21/04/13 08:51:29
. . . .
   bufdat exécuté                             678 (moyenne 0,0002/sec)

prêt  08:51:29
prêt  08:51:29

Figure 7 – Exécution du script « expect »

 

SSH :

Enfin, vous pouvez utiliser SSH pour exécuter une commande sur un système distant. Si vous avez également configuré l'authentification par clé publique, aucun mot de passe ne vous sera demandé au moment de l'exécution.

L'utilisation de SSH comporte quelques subtilités intéressantes. Tout d'abord, les abréviations ne fonctionnent pas : n'essayez pas d'exécuter « dps », mais utilisez plutôt « display_print_status ».

ssh [email protected] dbs                                                     
sh : dbs : commande introuvable
prêt  12:26:25

Figure 8 – L'utilisation de SSH pour exécuter à distance une commande abrégée ne fonctionne pas

ssh [email protected] display_batch_status                                    

Files d'attente de traitement par lots pour %phx_vos#m16

FILE                    ÉTAT   MAX           TÂCHES EN COURS D'EXÉCUTION
normal                    en cours      5
prête  12:26:43

Figure 9 – L'exécution à distance d'une commande via SSH fonctionne

 

Deuxièmement, l'exécution directe d'une macro de commande ne fonctionne pas ; notez qu'il n'y a pas de sortie et qu'il semble que seule la première commande de la macro ait été traitée.

ssh [email protected] 'foo.cm'                                                
affichage_de_l'utilisation_du_système
prêt  12:08:40

Figure 10 – L'utilisation de SSH pour exécuter à distance une macro de commande ne fonctionne pas toujours

 

Vous devez plutôt exécuter la commande shell et lui fournir la macro de commande en argument.

ssh [email protected] '/bin/sh foo.cm'
display_system_usage
Statistiques d'utilisation pour le module %phx_vos#m16, G94330, OpenVOS version 17.1.0ax
Total : 766,5 heures (31,9 jours) de fonctionnement.

----CPU-----         Dernière minute     5 dernières minutes       Dernière heure      Temps de fonctionnement total
Minutes CPU         0,02  0,5 %     0,09  0,4 %      0,91  0,4 %     724,76  0,4 %
. . . .
Temps interne           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 version 17.1.0ax, analyze_system version 17.1.0ax
Processus actuel : 922, ptep 8D3C2780, Noah_Davids.CAC

stcp_meters   %phx_vos#m16                766:30:14     21/04/13 12:08:57
. . .
   bufdat exécuté                             678 (moyenne 0,0002/sec)

prêt  12:08:59

Figure 11 – Utilisation de SSH pour exécuter à distance une macro de commande en la lançant sous forme de script shell

 

Les macros complexes ne fonctionneront pas. Par exemple, chaque ligne de la macro de commande est exécutée dans un processus distinct ; par conséquent, les macros qui utilisent la variable `process_dir` pour stocker des résultats intermédiaires ne fonctionneront pas. Notez que chaque appel à `analyze_system` renvoie un numéro de processus différent.

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 version 17.1.0ax, analyze_system version 17.1.0ax
Le processus actuel est 1028, ptep 8D3C3000, Noah_Davids.CAC
OpenVOS version 17.1.0ax, analyze_system version 17.1.0ax
Le processus actuel est 1029, ptep 8D3C3000, Noah_Davids.CAC
OpenVOS version 17.1.0ax, analyze_system version 17.1.0ax
Le processus actuel est 1030, ptep 8D3C3000, Noah_Davids.CAC
prêt  12:52:21

Figure 12 – Chaque commande de la macro est exécutée dans un processus distinct

 

L'utilisation de macros de commande avec des variables de type VOS génère des erreurs de syntaxe, car le shell ne les reconnaît pas. La macro de commande foo3.cm s'affiche, puis compte jusqu'à 9. La commande display est exécutée et « &set » génère une erreur de syntaxe.

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

Figure 13 – Les macros de commande utilisant des variables de type VOS ne fonctionneront pas

 

Mais l'utilisation de variables de shell fonctionnera. Cela peut bien sûr nécessiter une refonte importante des macros existantes. Voici un exemple de cette même macro sous forme de script 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
prêt  07:44:41

Figure 14 – Le script Shell utilisant des variables de type shell fonctionne

 

Cependant, vous pouvez exécuter votre macro de commande de type VOS en tant que processus lancé, puis afficher le fichier de sortie ainsi généré. La macro start_foo3.cm exécute start_process, attend que le processus se termine, puis affiche le fichier de sortie sans en-tête. J'ai modifié le fichier foo3.cm afin de désactiver les lignes de commande et de macro, ainsi que l'invite « ready », afin de reproduire plus fidèlement la sortie d'une macro de commande exécutée en mode interactif.

start_process foo3.cm -wait                                                   
display foo3.out -no_header

Figure 15 – Macro de commande permettant d'exécuter foo3.cm en tant que processus démarré

 

À l'exception de l'en-tête de connexion, du nom de la macro de commande sur les deux premières lignes et de la ligne « Process finished » à la fin, les résultats sont identiques à ceux obtenus si vous aviez exécuté la macro à partir de la ligne de commande 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

Figure 16 – Résultats de l'exécution de foo.cm dans un processus lancé

 

Comme vous pouvez le constater, même si vous ne pouvez pas utiliser Telnet, il existe d'autres moyens de se connecter automatiquement et d'exécuter des commandes.