Apprenez en lisant dans l'ordre

Combiner des commandes — agir selon le résultat de grep / awk

Cet article fait partie du Cours Linux, qui vous permet de maîtriser à partir de zéro des compétences Linux concrètes, des commandes de base jusqu'aux scripts shell.
Dans un script, mets un nombre dans une variable avec n=$(grep -c ERROR access.log), fais la somme avec total=$(awk '{s+=$1} END{print s}') et laisse if [ "$n" -ge 2 ] prendre la bonne branche — un scanner illustré et pratiqué dans un terminal en navigateur.

Appeler des commandes dans un script — pipes et substitution de commande

La vraie puissance d'un script shell, c'est que tu peux y combiner des commandes courantes comme `grep`, `awk`, `sed`, `sort` et `wc`.

Dans un script aussi, tu enchaînes les commandes avec un pipe | et tu récupères leur sortie avec la substitution de commande $(cmd).

Si tu écris n=$(grep -c error log.txt), le nombre de lignes correspondantes trouvé par grep -c est stocké dans la variable n.

Tu peux aussi mettre un résultat d'agrégation dans une variable, comme total=$(awk '{s+=$1} END{print s}' f).

Une fois le résultat d'une commande dans une variable, tu peux te servir de cette valeur pour changer le comportement du script.

printf 'INFO ok\nERROR disk\nINFO ok\nERROR cpu\n' > sys.log   # crée le fichier d'exemple
vi count.sh   # ouvre le fichier dans un éditeur, écris ceci, puis enregistre avec :wq
#   #!/bin/sh
#   n=$(grep -c ERROR sys.log)
#   echo "ERROR count: $n"
chmod +x count.sh
./count.sh                                                      # ERROR count: 2
Mettre un nombre dans une variable et prendre une branche
n=$(grep -c ERROR access.log)n ≥ 2afficher unavertissementn < 2afficher OK2 ou plusmoins de 2avertissementnormal
Le nombre compté par grep -c est stocké dans la variable n, et le if prend la branche d'avertissement à partir de 2, sinon il affiche OK.
SyntaxeSignificationExemple
n=$(grep -c pat f)Mettre le nombre de lignes correspondantes dans la variable nn=$(grep -c error log.txt)
$(cmd | cmd)Récupérer le résultat d'un pipe dans une variabletop=$(sort log.txt | head -1)
if [ "$n" -ge 2 ]; then …Prendre une branche selon que le nombre atteint 2 ou plusif [ "$n" -ge 2 ]; then echo warn; fi

Construis un scanner qui compte les erreurs d'un log d'accès avec grep -c et affiche un avertissement dès 2 erreurs, ou OK sinon.

① Lance printf 'INFO login\nERROR timeout\nINFO logout\nERROR 500\nINFO ping\n' > access.log pour créer le fichier d'exemple.

② Ouvre scan.sh avec vi scan.sh et appuie sur i pour passer en mode insertion. Mets le nombre dans une variable avec n=$(grep -c ERROR access.log), puis affiche soit WARN: $n errors found soit OK avec if [ "$n" -ge 2 ]; then … else … fi (mets #!/bin/sh sur la première ligne). Quand c'est écrit, appuie sur Esc:wq pour enregistrer.

③ Rends le script exécutable avec chmod +x scan.sh, lance ./scan.sh et vérifie que l'avertissement s'affiche bien.

④ Si tu ne sais pas quoi écrire, tu peux copier le contenu depuis le panneau de réponse et le coller dans le mode insertion de vi.

(Exécute-le correctement et l'explication apparaîtra.)

Linux console
0 / 3 exécutée(s)
Loading Linux Terminal...

Agréger, puis changer de comportement selon le résultat — awk et branchement

Au-delà des comptages, tu peux aussi additionner des nombres et décider à partir du total.

total=$(awk '{s+=$1} END{print s}' f) additionne la colonne 1 de chaque ligne et met la somme dans la variable total.

Quand tu veux le nombre d'occurrences par mot, trie d'abord, puis compte, avec sort f | uniq -c, et récupère ce résultat avec $(...).

En comparant la somme à un seuil, comme dans if [ "$total" -gt 100 ]; then …, tu peux décider par exemple d'avertir dès que le total dépasse une limite.

Réunis l'agrégation et le branchement dans un seul script : tu obtiens un vrai outil qui lit des données et évalue la situation.

printf '40\n30\n50\n' > sales.txt   # données numériques sur une colonne
vi sum.sh   # ouvre le fichier dans un éditeur, écris ceci, puis enregistre avec :wq
#   #!/bin/sh
#   total=$(awk '{s+=$1} END{print s}' sales.txt)
#   if [ "$total" -gt 100 ]; then
#     echo "total $total: goal met"
#   else
#     echo "total $total: not met"
#   fi
chmod +x sum.sh
./sum.sh                              # total 120: goal met
printf 'a\na\nb\n' > tags.txt   # fichier d'exemple avec des mots répétés
sort tags.txt | uniq -c          # trier en premier, puis compter
# Sortie :
#   2 a
#   1 b
Additionner un total et prendre une branche selon sa valeur
total=$(awk … errors.txt)total > 20action requisetotal ≤ 20dans la limiteau-dessusen dessousseuil dépasséseuil respecté
if compare le total additionné par awk au seuil 20 : au-dessus il prend la branche « action requise », sinon la branche « dans la limite ».
SyntaxeSignificationExemple
awk '{s+=$1} END{print s}' fAdditionner la colonne 1awk '{s+=$1} END{print s}' nums.txt
sort f | uniq -cTrier avant de compter les occurrencessort tags.txt | uniq -c
if [ "$total" -gt N ]; then …Prendre une branche en comparant le total au seuil Nif [ "$total" -gt 100 ]; then …

Construis un script qui additionne des données numériques avec awk et change son résultat selon qu'il dépasse un seuil ou non.

① Lance printf '12\n8\n5\n3\n' > errors.txt pour créer des données numériques sur une colonne.

② Ouvre sum.sh avec vi sum.sh et appuie sur i pour passer en mode insertion. Mets la somme dans une variable avec total=$(awk '{s+=$1} END{print s}' errors.txt), puis affiche soit needs action: total $total soit within limit: total $total avec if [ "$total" -gt 20 ]; then … else … fi (mets #!/bin/sh sur la première ligne). Quand c'est écrit, appuie sur Esc:wq pour enregistrer.

③ Rends le script exécutable avec chmod +x sum.sh, lance ./sum.sh et vérifie que le résultat correspondant au total s'affiche.

④ Si tu ne sais pas quoi écrire, tu peux copier le contenu depuis le panneau de réponse et le coller dans le mode insertion de vi.

Linux console
0 / 3 exécutée(s)
Loading Linux Terminal...

Rediriger la sortie et les erreurs — > et 2>

Tu veux parfois garder le résultat d'un script dans un fichier plutôt qu'à l'écran.

./scan.sh > report.txt écrit la sortie normale (la sortie standard) dans report.txt.

Envoie les messages d'erreur vers l'erreur standard avec echo "..." 1>&2 : avec ./scan.sh > report.txt 2> error.log, tu gardes les résultats normaux et les erreurs dans des fichiers séparés.

vi job.sh   # ouvre le fichier dans un éditeur, écris ceci, puis enregistre avec :wq
#   #!/bin/sh
#   echo "processing started"          # sortie standard
#   echo "note: input was empty" 1>&2   # erreur standard
chmod +x job.sh
./job.sh > out.txt 2> err.txt        # sortie et erreurs vers des fichiers séparés
cat out.txt                          # processing started
cat err.txt                          # note: input was empty
Rediriger la sortie et les erreurs
./scan.shsortie d'echo(stdout)> report.txt./scan.shecho … 1>&2(stderr)2> error.logsortie standarderreur standard
La sortie standard part vers > report.txt et l'erreur standard vers 2> error.log, redirigées séparément.
SyntaxeSignificationExemple
cmd > outÉcrire la sortie standard dans un fichier./scan.sh > report.txt
echo "…" 1>&2Envoyer un message vers l'erreur standardecho "failed" 1>&2
cmd > out 2> errRediriger la sortie et les erreurs vers des fichiers séparés./scan.sh > report.txt 2> error.log

Construis un script qui redirige un message normal et un message d'erreur vers des fichiers séparés.

① Ouvre job.sh avec vi job.sh et appuie sur i pour passer en mode insertion. Envoie echo "done" vers la sortie standard et echo "warning" 1>&2 vers l'erreur standard (mets #!/bin/sh sur la première ligne). Quand c'est écrit, appuie sur Esc:wq pour enregistrer.

② Rends le script exécutable avec chmod +x job.sh, puis sépare la sortie et les erreurs en deux fichiers avec ./job.sh > out.txt 2> err.txt.

③ Lance cat out.txt et cat err.txt, et vérifie que le message normal et le message d'erreur sont bien chacun dans leur fichier.

④ Si tu ne sais pas quoi écrire, tu peux copier le contenu depuis le panneau de réponse et le coller dans le mode insertion de vi.

Linux console
0 / 3 exécutée(s)
Loading Linux Terminal...
QUIZ

Vérification des connaissances

Répondez à chaque question une par une.

Question 1Que met n=$(grep -c error log.txt) dans la variable n ?

Question 2Que fait if [ "$n" -ge 2 ]; then … ?

Question 3Dans ./scan.sh > report.txt 2> error.log, que redirige 2> ?