TP 05 - Automatisation en ligne de commande

Concepts

L'automatisation des tâches fait référence à la délégation/décharge des actions de l'utilisateur aux programmes du système informatique. Un programme effectuera automatiquement, de lui-même, des actions que l'utilisateur ferait, ce qui lui fera gagner du temps.

Les actions candidates à l'automatisation sont généralement des actions répétitives, peu simples et non interactives. Leur automatisation libérera l'utilisateur de leur exécution manuelle, répétitive et fastidieuse.

Commande Brève description
cat comment afficher le contenu du fichier
seq génère une séquence de nombres
grep extrait les lignes contenant une expression régulière spécifique
cut extraire certaines colonnes
sed filtre de texte avancé utilisé pour les substitutions
wc compter le nombre de lignes, de mots ou de caractères
head afficher les premières lignes ou caractères
tail afficher les dernières lignes ou caractères
for parcourir la liste des éléments pour appliquer des commandes à chaque élément
if condition d'exécution de certaines commandes
$(comm) expansion d'une commande (extension de commande) - remplacement par la sortie de la commande
comm1 | comm2 reliant deux commandes : la sortie de la première commande devient l'entrée de la deuxième commande
$var ou ${var} la valeur de la variable var
${#var} longueur de la valeur de la variable var (en caractères)
${var:2:3} une sous-chaîne de la valeur de la variable var : 3 caractères sont extraits de l'index 2

Scripting

La création de scripts implique l'utilisation d'un langage interprété (appelé langage de script). Cela peut être un langage comme Python, Perl ou Ruby, ou même le shell CLI (interpréteur de commandes). Les langages de script ont l'avantage de se développer rapidement : nous ajoutons et testons rapidement de nouvelles fonctionnalités.

Les scripts shell ont l'avantage d'utiliser les commandes shell existantes (commandes de fichiers, commandes de processus, commandes de filtrage de texte). Pour les actions rapides (quick'n'dirty), les scripts shell sont une très bonne solution. Lorsque l'on a des manipulations numériques ou des manipulations de chaînes, les scripts shell peuvent être insuffisants et il est conseillé de se tourner vers un langage de script plus complet, comme Python, Ruby ou Perl.

Fonctions du shell

Les fonctionnalités du shell sont utilisées dans l'efficacité et l'automatisation de l'exécution des commandes. Je les ai utilisés et je m'en suis souvenu lors des derniers laboratoires, en particulier le dernier laboratoire. Ces fonctionnalités sont :

  • redirection des commandes dans les fichiers, à l'aide des opérateurs de redirection : >, <, »
  • rediriger la sortie d'une commande vers l'entrée d'une autre commande : l'opérateur | (pipe)
  • variables d'interpréteur de commandes
  • échapper à l'aide de backslash, de guillemets ou d'apostrophes

Tout au long de ce TP, nous utiliserons des fonctionnalités shell spécifiquement utilisées dans les scripts shell :

  • expressions régulières
  • arguments de la ligne de commande
  • commandes shell internes pour le contrôle de flux : if, for, while

Automatisation via des scripts shell

L'automatisation via les scripts shell implique généralement une séquence de commandes. Ces commandes sont ajoutées à un script où elles seront exécutées ensemble, sans qu'il soit nécessaire d'exécuter manuellement chaque commande.

Pour configurer l'exécution d'une séquence de commandes, nous pouvons conditionner l'exécution du script à l'aide de variables ou d'arguments dans la ligne de commande. Ceux-ci peuvent générer un comportement de script différent en fonction de leurs valeurs.

En fonction de variables, d'arguments de ligne de commande ou de données d'entrée, un script peut prendre des décisions conditionnelles. La vérification d'une condition peut conduire à un comportement ou à un autre.

Lors de l'exécution d'un script, nous voudrons souvent qu'une action cible plusieurs fichiers, processus ou chaînes. Pour cela, nous verrons comment utiliser des boucles pour parcourir des listes d'éléments.

Les commandes utilisées peuvent recevoir en argument ou en entrée standard la sortie d'autres commandes. Dans les scripts shell, nous utilisons des fonctionnalités de chaînage de commandes telles que l'expansion de commandes ou des pipes conduisant à des résultats plus complexes.

Basics

Expressions régulières et grep

Dans le répertoire du référentiel du laboratoire, il y a un fichier Students.txt que nous utiliserons comme support pour les commandes d'expressions régulières. Ce fichier contient une liste d'étudiants avec le nom complet des étudiants (première colonne), leur groupe (deuxième colonne) et diverses notes USO (note finale - troisième colonne, note du test de la grille - quatrième colonne - et note du test pratique - cinquième colonne), champs séparés par le caractère de tabulation.

Pour rechercher et sélectionner des lignes dans des fichiers texte, nous utilisons la commande grep, qui à son tour utilise des expressions régulières. Ainsi, si nous voulons sélectionner les étudiants qui ont la lettre z dans leur nom, nous utilisons la commande

student@uso:~/uso-lab/labs/06-scripting/support/00-basics$ grep 'z' students.txt 
GHECENCO F. Răzvan	312CC	8	8.75	4.67
MARIN N. Răzvan	312CC	5	3.5	4.2

Il est recommandé que l'argument d'expression régulière passé à la commande grep soit entouré de guillemets simples (') pour être échappé. De cette façon, les caractères de l'expression régulière seront transmis exactement à la commande grep et ne seront pas interprétés par le shell.

Ainsi, la commande grep pour extraire les étudiants dont le nom commence par la lettre F est

student@uso:~/uso-lab/labs/06-scripting/support/00-basics$ grep '[ -]F[a-z]\+[^\.]' students.txt 
ONEA I. Flavia-Katilina	311CC	7	6.5	4.33
EPURE P. Andi-Florin	314CC	8	9.5	3.67
NEACȘU C. Florin-Mărgărit	314CC	10	9	9
COSTEA I. Florin Traian	315CC	4	3.5	3.7
CHIȚESCU E. Bogdan-Florentin	315CC	9	7.75	6.89

tr & sed

L'utilitaire tr permet la traduction, la suppression et la manipulation des caractères reçus en entrée. Fondamentalement, sed est un éditeur de flux qui peut effectuer des transformations au niveau de la chaîne sur un texte reçu en entrée. De plus, sed peut accepter des expressions régulières comme argument de recherche.

La différence entre tr et sed est que le premier effectue des transformations au niveau des caractères, tandis que le second effectue des transformations au niveau des chaînes. Pour cette raison, nous pouvons dire que sed est un tr, tr++ plus avancé :).

Par exemple, en utilisant à la fois tr et sed, remplaçons le caractère ',' par TAB dans student.csv :

student@ubuntu:~/uso-lab/labs/06-scripting/support/00-basics$ cat students.csv | tr , "\t" > students.out
student@ubuntu:~/uso-lab/labs/06-scripting/support/00-basics$ cat students.out 
VLĂDUȚU I. Liviu-Alexandru	311CC	6	3.5	5.22
GEORGIU V. Alexandra-Maria	311CC	10	10	9.67
PĂUNOIU N. Gabriel	311CC	7	6.5	3.5
BĂCÎRCEA A. Andrei	311CC	7	5.5	4.44
[...]
 
student@ubuntu:~/uso-lab/labs/06-scripting/support/00-basics$ sed 's/,/\t/g' students.csv > students.out 
student@ubuntu:~/uso-lab/labs/06-scripting/support/00-basics$ cat students.out 
VLĂDUȚU I. Liviu-Alexandru	311CC	6	3.5	5.22
GEORGIU V. Alexandra-Maria	311CC	10	10	9.67
PĂUNOIU N. Gabriel	311CC	7	6.5	3.5
BĂCÎRCEA A. Andrei	311CC	7	5.5	4.44
[...]

cut

Nous pouvons extraire des informations structurées sur les lignes et les colonnes à l'aide de l'utilitaire cut:

student@ubuntu:~/uso-lab/labs/06-scripting/support/00-basics$ cat /etc/passwd | cut -d':' -f1,6 | head -3
root:/root
daemon:/usr/sbin
bin:/bin

sort & uniq

Si nous voulons trier les élèves du fichier dans l'ordre de leurs noms, nous utiliserons la commande sort :

student@uso:~/uso-lab/labs/06-scripting/00-basics$ sort students.csv 
ALECU C. Ionuț-Gabriel,312CC,7,4.5,6.4
ASĂVOAEI P. Cătălin,315CC,8,6.75,7
BĂCÎRCEA A. Andrei,311CC,7,5.5,4.44
BADEA P. Bogdan,314CC,4,2.75,1.56
[...]

Certaines options souvent utilisées avec sort sont :

  • -t spécifie le séparateur
  • -k spécifie l'index, ou la clé, de la colonne par laquelle nous voulons trier les entrées
  • n tri numérique (la valeur par défaut est alphabétique)
  • -r tri inversé (ascendant par défaut)

Nous voulons faire un tri numérique décroissant par année, suivi d'un tri alphabétique par groupe (c'est-à-dire toutes les années commençant par 10 mais triées par ordre de groupe). Ainsi, pour trier les entrées dans l'ordre des notes, nous utiliserons le séparateur , (virgule, virgule) et la 3ème colonne pour la clé :

student@uso:~/uso-lab/labs/06-scripting/support/00-basics$ sort -t ',' -k 3,3nr -k 2,2 students.csv
GEORGIU V. Alexandra-Maria,311CC,10,10,9.67
MUȘATESCU V. Alexandru-Petrișor,311CC,10,8.5,9
RADU L. Alina,311CC,10,10,7.89
GONDOȘ I. Gabriel,312CC,10,9,7.33
[...]

S'il y a des lignes en double, nous pouvons utiliser l'utilitaire uniq en conjonction avec sort pour les supprimer. Pour cela, nous ajoutons une ligne dupliquée dans Students.csv :

student@uso:~/uso-lab/labs/06-scripting/support/00-basics$ sort -t ',' -k 3,3nr -k 2,2 students.csv | wc -l
93
student@uso:~/uso-lab/labs/06-scripting/support/00-basics$ sort -t ',' -k 3,3nr -k 2,2 students.csv | uniq | wc -l
92
student@uso:~/uso-lab/labs/06-scripting/support/00-basics$ uniq students.csv | wc -l
93

Shell scripting

Un script shell est un fichier texte qui contient des commandes et des constructions spécifiques au shell. Un script shell commence par la construction #!/bin/bash, appelée un shebang qui indique l'interpréteur du script ; dans ce cas, l'interpréteur est le shell Bash lui-même. Si aucun shell n'est spécifié via shebang, le shell par défaut (défini dans /etc/passwd) attribué à l'utilisateur connecté sera pris par défaut.

Par exemple, les one-liners que j'ai écrits jusqu'à présent pourraient être mis dans un script shell et, de plus, s'il s'agit de longues commandes et qu'elles ne tiennent pas sur une seule ligne, nous pouvons les “casser” en plusieurs lignes en utilisant le séparateur \ :

#!/bin/bash
 
export DATE=$(date +20%y%m%d) && \
mkdir -p /usr/share/snapshots && \
tar -cvpzf /usr/share/snapshots/$HOSTNAME_$DATE.tar.gz \
    --exclude=/proc --exclude=/lost+found \
    --exclude=/sys --exclude=/mnt \
    --exclude=/media --exclude=/dev \
    --exclude=/share/Archive /

ATTENTION! Dans la construction ci-dessus après \ il ne doit plus y avoir de caractères (pas même d'espaces à la fin)

Le script contient des commandes courantes utilisées dans le shell et d'autres commandes que l'on trouve plus souvent dans les scripts : while, if, for. Ce ne sont pas des instructions, ce sont toujours des commandes shell ; peut également être utilisé, si la syntaxe est correcte, sur la ligne de commande.

Arguments de la ligne de commande

Un script hérite des variables d'environnement du shell parent telles que HOME, BASH, IFS, USER. Dans le script, nous pouvons les utiliser comme ceci :

#!/bin/bash
 
echo $HOME

En plus de ces variables, le script peut recevoir un certain nombre d'arguments de ligne de commande. En utilisant les variables suivantes, nous pouvons faire référence aux arguments reçus par le script depuis la ligne de commande :

  • $* est une chaîne ($1, $2 … $n) composée de tous les arguments reçus par le script
  * ''$@ est une liste d'arguments de script * $1, $2 … $n'' représente chaque paramètre du script
  * ''$0 est le nom du script * $#'' est le nombre d'arguments reçus de la ligne de commande
Par exemple, prenons le script arguments.sh suivant :
<code bash>
echo There are $# arguments to $0: $*

echo first argument: $1
echo second argument: $2 echo third argument: $3
echo the list of arguments: $@ </code>

student@uso:~$ ./arguments.sh banane cirese caise castraveti
   There are 4 arguments to arguments.sh: banane cirese caise castraveti
   first argument: banane
   second argument: cirese
   third argument: caise
   the list of arguments: banane cirese caise castraveti

La construction while read

Créez un nouveau script extract-name avec le contenu suivant :

#!/bin/bash
 
IFS=','
while read name group final_grade test_grade practical_grade; do
    echo "$name"
done < students.csv

Pour l'analyse dans le shell, nous utilisons la construction while read …. La construction est suivie des noms des variables dans lesquelles nous retiendrons les champs analysés à l'intérieur de chaque ligne. Nous utilisons le fichier Students.csv dans le répertoire parent comme entrée ; est un fichier au format CSV (Comma Separated Values) utilisant le caractère virgule (,, virgule) comme séparateur. Pour extraire uniquement les noms des étudiants du fichier d'entrée, nous allons exécuter le script extract-name :

student@uso:~/uso-lab/labs/06-scripting/support/00-basics$ ./extract-name
VLĂDUȚU I. Liviu-Alexandru
GEORGIU V. Alexandra-Maria
PĂUNOIU N. Gabriel
BĂCÎRCEA A. Andrei
[...]

Étant donné que le format d'entrée utilise une virgule (,, virgule) comme séparateur, nous avons défini la variable interne IFS (Internal Field Separator) dans le script à la valeur ',', comme nous le voyons à la ligne 3 du script extract-name :

IFS=','

if statement

Nous pouvons étendre le script ci-dessus pour afficher uniquement les étudiants dont la moyenne est supérieure à 5.

#!/bin/bash
 
IFS=','
while read name group final_grade test_grade practical_grade; do
    if test "$final_grade" -gt 5; then
        echo "$name,$group,$final_grade"
    fi
done < students.csv

for loop

Il existe également des constructions de type for dans bash. Un exemple courant consiste à parcourir le contenu d'un répertoire et à effectuer des opérations sur les fichiers. Par exemple, nous souhaitons sauvegarder tous les fichiers d'un répertoire envoyé en paramètre au script :

#!/bin/bash
 
for file in $1/*
do
    if test -f $file; then
        stat --print="%a %F %n\n" $file
        cp $file $file.bkp
    fi
done
#!/bin/bash
 
for file in $(find /usr/share/pixmaps/ -type f -iname '*.jpg')
do
    echo $file
done

Exercices

01. Alias

Dans cet ensemble d'exercices/tutoriels, nous verrons comment utiliser les alias pour rendre les actions plus efficaces.

Commençons par utiliser la commande xdg-open dans les formulaires ci-dessous :

xdg-open .
xdg-open http://google.com
<code>
 
Ces commandes ouvrent respectivement un navigateur de fichiers, un navigateur web.
 
Pour effectuer des actions plus rapidement, nous utilisons un alias. Nous créons des alias open et go pour xdg-open comme ci-dessous :
<code bash>
alias open='xdg-open'
alias go='xdg-open'

Exercice : Utilisez maintenant la commande open ou la commande go pour les deux actions ci-dessus. Nous avons simplifié la commande xdg-open (plus difficile à écrire et plus difficile à retenir).

02. One liners

Saisissez le sous-répertoire noms-indexés/. Nous voulons effectuer des opérations automatiques sur le système de fichiers, en utilisant les lignes for et one.

Nous exécutons les deux commandes ci-dessous :

for i in $(seq -f "%02g" 1 3); do touch test-"$i".txt; done
for i in $(seq -f "%02g" 0 12); do mkdir uso-curs-"$i"; done

A la fin de l'exécution de ces commandes, on obtient 3 fichiers texte (pour les 3 papiers/tests) et 13 répertoires, pour les 13 répertoires. J'ai utilisé for pour parcourir une liste et seq pour créer une liste numérique.

Exercice : Créez une doublure qui crée les 13 répertoires et crée dans chaque répertoire un sous-répertoire appelé slides/, un fichier appelé notes.txt et un fichier appelé resources.txt.

03. One liners vs commands

Nous exécutons les commandes suivantes pour générer un mot de passe à 16 caractères et afficher les PID des processus utilisateur étudiants :

tr -dc 'a-zA-Z0-9~!@#$%^&*_()+}{?></";.,[]=-' < /dev/urandom | fold -w 32 | head -n 1
ps -ef | grep student | tr -s ' ' | cut -d ' ' -f 2

04. Scripts simples

Exercice : Pour désactiver le montage des clés USB sur le système, nous pouvons utiliser les commandes :

sudo rmmod uas
sudo rmmod usb_storage

Ensuite, pour réactiver, on utilise les commandes :

sudo modprobe usb_storage
sudo modprobe uas

Créez des scripts disable-usb et enable-usb pour désactiver et activer le montage de la clé USB, respectivement. Exécutez-les pour vérification.

Exercice : Créez un script appelé system-info qui affiche les informations système dans le modèle ci-dessous :

date: 2019-11-05
kernel: 5.0.0-32-generic
version: Ubuntu 18.04.3 LTS
num_processes: 336
sde2/laboratoare/05_uso.txt · Last modified: 2023/04/11 10:16 by cristiana.andrei
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0