Capsule : Scripts systèmes

Introduction

L’objet du module 122 est la réalisation de scripts dans le contexte de l’administration de systèmes informatiques. Cette capsule a pour but de préciser ce que l’on entend par script et en quoi un script se distingue d’un utilitaire ou d’une application. Pour cela, nous explorons d’abord brièvement les raisons de réaliser un script, puis les contraintes liées à l’exécution sans interaction avec un utilisateur et enfin un certain nombre de risques liés à l’utilisation de script. En guise de conclusion, on vous propose un certain nombre de critères permettant de justifier la réalisation d’un script.

Quand et pourquoi écrire un script ?

Administrer un système informatique consiste à en assurer l’adéquation aux besoins des utilisateurs et à en assurer le bon fonctionnement en toutes circonstances. Cela implique une grande variété de tâches plus ou moins complexe, qui doivent être réalisées de manière plus ou moins fréquente et plus ou moins prévisible ou dont l’exécution est déclenchée par la survenue d’un événement particulier.

Considérons, par exemple, des tâches telles que l’ajout d’un nouvel utilisateur, le démarrage d’une sauvegarde ou la mise à jour d’un composant logiciel. Chacune d’elle peut être exécutée de manière interactive en effectuant, au moment voulu, les actions nécessaires dans l’interface en ligne de commande (CLI) ou l’interface graphique (GUI) du système d’exploitation. Toutefois, cette manière de procéder comporte un certain nombre de risques, par exemple :

  • Risque d’oublier une tâche peu fréquente ou de l’exécuter plusieurs fois.
  • Risque de ne pas apercevoir la survenue d’un événement nécessitant une action.
  • Risque de se rappeler de manière erronée ou de manière incomplète la procédure à suivre pour réaliser une tâche.
  • Risque d’oublier la procédure à suivre.
  • Risque de reproduire de manière incorrecte une procédure connue.
  • Risque de ne pas pouvoir retracer la totalité des actions effectuées en cas de problème.
  • Risque de surcharge de travail lorsqu’un grand nombre de tâches doivent être réalisées en même temps (arrivée d’un grand nombre de nouveaux utilisateurs, conjonction d’un certain nombre d’événements ).

Pour mitiger certains de ces risques, il est nécessaire de prendre quelques précautions, notamment :

  • Décrire les procédures à l’aide de marches à suivre,
  • suivre la progression d’une procédure avec une liste de contrôle,
  • dater et consigner les listes de contrôle dans un journal,
  • utiliser un calendrier,

Il apparaît que pour toute action non triviale, il est nécessaire de réaliser un certain nombre de documents, dont une marche à suivre. Mais si l’on considère qu’une marche à suivre n’est rien d’autre qu’une séquence d’instructions (une liste de commandes), éventuellement agrémenté de quelques commentaires, on se rend compte qu’une marche à suivre n’est rien d’autre qu’un programme.

Une fois ce fait établi, l’intérêt d’une interface en ligne de commande devient évident. En effet, comme un CLI reçoit des commandes sous la forme de texte, il suffit, pour automatiser une tâche, d’écrire la liste des commandes dans un fichier de texte puis d’envoyer son contenu dans l’entrée standard du CLI. De plus, la plupart des langages de commande permettent l’ajout de lignes de commentaires ; Bash et PowerShell ignorent les lignes qui commencent par le caractère #, l’IOS de Cisco ignore celles qui commencent par ! et le cmd.exe de Windows, celles qui commencent par REM.Par rapport à une interface graphique (GUI), le principal avantage d’une interface en ligne de commande (CLI) est de permettre de facto l’automatisation d’une tâche puisqu’il suffit pour cela d’écrire les commandes dans un fichier de texte et d’envoyer le contenu dans son entrée standard. Le CLI des systèmes d’exploitations modernes est en fait le mode interactif de l’interpréteur du langage de commande (bash ou powershell), il n’est donc pas nécessaire d’avoir recours à la redirection des entrées/sorties. De plus, on peut utiliser l’extension sous Windows ou le shebang (#!) sous Linux, pour rendre un fichier directement exécutable.

Avant de finir cette section, encore un mot sur la terminologie. Pourquoi parle-t-on de script plutôt que de programme ? Outre le fait que c’est le terme consacré par l’usage et qu’il serait absurde d’aller à l’encontre, à la différence de l’interpréteur python, par exemple, qui dispose également d’un mode interactif mais dont la fonction première est l’exécution de programme, la fonction première de l’interpréteur bash ou de l’interpréteur powershell est celle d’interface utilisateur pour le système d’exploitation. C’est pourquoi, dans le cas d’un programme bash ou d’un programme powershell, il convient de parler de script.

En bref, il convient d’écrire un script pour toute action non triviale sur un système informatique. En effet, non seulement un script permet de documenter l’action comme le ferait un document fournissant une marche à suivre, mais il permet surtout d’automatiser cette action et de la rendre reproductible.

Exécution sans interaction avec un utilisateur

L’interaction avec l’utilisateur est importante source d’erreur, mais elle a également quelques avantages. En effet, lorsqu’un programme est utilisé de manière interactive, il est facile d’informer l’utilisateur de la manière dont se déroule l’exécution de la tâche et, en cas de problème, de lui demander d’entreprendre une action correctrice.

Si l’on réduit l’interaction à zéro, ce qui est souhaitable pour la fiabilité et la reproductibilité, voire même nécessaire si l’on veut que la tâche puisse être exécutée sans surveillance (tâches planifiées, login script, startup/shutdown script, etc. ), il est impératif que le script puisse laisser une trace de la manière dont la procédure s’est déroulée. Si elle se déroule avec succès, une simple entrée dans un fichier de journal (log file) suffit. Si une erreur survient en cours d’exécution, il suffit d’inscrire au journal toutes les informations pertinentes sur l’état du système avant de réessayer l’opération. Mais si l’erreur persiste et que la procédure doit être abandonnée, l’inscription de l’échec peut ne pas suffire. En effet, s’il s’agit d’une procédure critique il faut également s’assurer que l’information ne passe pas inaperçue en notifiant d’une manière ou d’une autre la personne responsable. Bien qu’il soit possible de réaliser tout cela de manière ad hoc dans chacun de nos scripts, il est préférable d’utiliser les journaux d’événements du système d’exploitation et d’avoir recours à un système de surveillance des journaux pour la notification.

Voyons d’abord les journaux d’événements. Dans les systèmes de la famille Unix, les entrées des journaux sont le plus souvent stockées dans des fichiers de textes avec l’extension .log (log files) rassemblés dans le répertoire /var/log. Toutefois, seul l’utilisateur root dispose d’un accès en écriture à ce répertoire, ce qui indique que nous ne sommes pas censés l’utiliser directement. En effet, ce répertoire est typiquement sous le contrôle du démon syslogd (ou rsyslogd) qui implémente le protocole syslog et qui est plus ou moins l’équivalent du service EventLog de Windows. L’inscription d’une entrée dans un journal doit donc se faire à l’aide de la commande logger. Avec les systèmes de la famille Windows, la manière d’inscrire un événement dans un journal dépend du langage de commande utilisé : avec la commande evencreate pour cmd.exe et avec la commande Write-EventLog pour PowerShell. En utilisant les journaux d’événements du système, il n’est pas nécessaire de se préoccuper du format des inscriptions (date, process id, etc.) ou de la manière de stocker ces inscriptions (fichier, base de données, ordinateur distant, etc.) le système s’en charge pour nous. De plus, il est possible de modifier ces paramètres sans avoir à toucher aux scripts. Sous Linux, ces paramètres sont stockés dans le fichier de configuration du démon : /etc/syslog.conf ou /etc/rsyslog.conf. Sous Windows, ces paramètres sont stockés dans la base de registre et peuvent être modifiés avec la commande New-EventLog.

L’utilisation des journaux d’événements du système nous épargne également la préoccupation de la notification. En effet, chaque système dispose d’outils de surveillance (monitoring) capable de déclencher (trigger) une action lorsqu’un certain type d’événement survient. Sous Windows, une telle fonctionnalité est intégrée à l’observateur d’événement qui permet d’associer une tâche à un type d’événement. Sous Linux, en revanche, conformément au premier principe de la philosophie d’Unix : « Make each program do one thing », le démon syslogd ne se prend pas en charge cette fonctionnalité. Pour cela, on aura recours à une application de surveillance système telle que Nagio par exemple. Toutefois, au besoin, il relativement simple de surveiller un fichier log à l’aide d’un script.

Pour résumer, un script devrait fonctionner sans nécessiter d’interaction avec un utilisateur, d’une part pour augmenter la reproductibilité et réduire le risque d’erreur et d’autre part pour permettre l’exécution sans surveillance (unattended) de tâches planifiées, de script d’ouverture de session ou encore de scripts de démarrage et d’arrêt. Toutefois, il est important que le script laisse une trace de la manière dont s’est déroulée son exécution (l’équivalent d’une liste de contrôle) que la personne responsable soit notifier en cas d’échec d’une tâche critique. Pour cela, il est recommandé d’utiliser les journaux d’événements du système d’exploitation et une application de surveillance système existante pour la notification.

Risques

La réalisation d’un script comporte certains risques, notamment :

  • Risque d’overengineering
  • Risque d’être utilisé par des personnes non compétentes.
  • Risque d’oublier une tâche planifiée.

Overengineering

Lorsqu’une première version du script est réalisée, il peut être tentant de vouloir le paramétrer de manière à prendre en compte différents cas d’utilisation qui pourraient hypothétiquement se présenter. Cela constitue un cas de suringénierie (overengineering). Il est important de considérer un script comme la documentation et l’automatisation d’une procédure particulière applicable à un système particulier. Un script doit être aussi simple que possible.

Utilisation inappropriée

Un script doit être simple à utiliser, même la procédure qu’il automatise peut être complexe et susceptible de compromettre le bon fonctionnement du système. Un script n’est pas un moyen de remplacer le jugement d’un professionnel.

Oublie d’une tâche planifiée

Un script ne doit pas s’exécuter silencieusement. Si la procédure est exécutée de manière non interactive, il est important que chaque exécution fasse l’objet d’une inscription dans un journal et que l’administrateur puisse être notifié en cas d’erreur. L’illustration de la figure 1 décrit une scène dans laquelle une tâche planifiée chargée d’effectuer un backup échoue silencieusement depuis près de deux ans.

Y a-t-il un backup dans l'avion ?
Fig. 1 – Y a-t-il un backup dans l'avion ?

Conclusion

La réalisation d’un script ne devrait pas prendre plus de temps que la réalisation d’une documentation adéquate de la procédure qu’il sert à automatiser et ne devrait donc pas demander de justification. Toutefois, et en guise de conclusion, voici quelques critères qui peuvent aider à justifier la création d’un script, en cas de besoin :

  • Une même procédure doit être exécutée un grand nombre de fois.
  • La tâche est récurrente.
  • La tâche est rarement exécutée et nécessite une marche à suivre écrite.
  • La tâche n’est réalisée qu’une fois, mais elle est complexe ou risquée (déploiement, migration).
  • La tâche doit pouvoir être exécutée sans interaction avec un utilisateur (backup, surveillance, etc.)