La vraie puissance de ces outils apparaît quand on les combine. Le pipe (la barre verticale | ) passe la sortie d’une commande en entrée de la suivante :
# Dans les logs Apache, extraire les IPs des erreurs 500 et les compter
# par occurrence
grep " 500 " access.log | awk '{print $1}' | sort | uniq -c | sort -rn
Cette inefficacité remarquable à programmer en Shell apparaît nettement dans cet exemple. On entremêle succinctement des utilitaires de façon erratique. Le Shell est décrit comme étant un outil commode : courant, pratique et fiable.
Mais comment expliquer les multiples solutions insatisfaisantes sensées résorber le problème ? Si vous ne me croyez pas, il suffit de consulter des solutions sur Stack Exchange.
La ligne de commande semble convenir à première vue. Finalement, ce n’est pas aussi simple qu’escompté. On éprouve toute cette complexité en ressortant avec des commandes tortueuses. Parcourir les manuels des utilitaires, expérimenter, recomposer à nouveau en cas d’échec. Pour quoi ? Déboucher sur une ligne de commande qui nous aurait pris un temps fou pour y parvenir.
Sérieusement, le Shell n’est pas le bon outil. On aurait pu obtenir le même résultat sans effort avec un programme Python.
Simple ne veut pas dire facile et tout le monde n’apprend pas à utiliser le manuel ou à utiliser correctement les outils à sa disposition, ce qui explique les solutions sur Stack Exchange
Comme dit en bas, il n’existe pas une solution, mais des solutions
Le shell est un outil comme un autre et une personne qui sait programmer en shell te sortira le même commentaire sur le Python :)
Pour moi, il est plus facile d’enchaîner les commandes shell que faire un programme en Python, qui en plus pourra être plus lourd qu’un outil système déjà présent (et sûrement compilé en C)
Selon moi, le truc le plus important : sort, uniq, grep, awk sont des utilitaires UNIX/POSIX. Ils sont disponibles partout (OpenBSD, Linux, FreeBSD, AIX, Solaris). Ils fonctionnent donc de manière quasi-universelle et ne demandent aucune stack à installer. Ton programme en Python demande un environnement Python et sera sûrement rempli de fonctions spécifiques qui ne sont pas interopérables avec le reste.
“Le mieux est l’ennemi du bien”, comme dirait l’autre
On peut certainement chaîner des commandes efficacement et obtenir un résultat valable. Mais cela représente une charge mentale non négligeable. Il faut bien comprendre les divers utilitaires ainsi que le fonctionnement du Shell.
On se croirait au début du XXIe siècle concernant la remarque artificielle sur la disponibilité des ressources. Ne va pas me faire croire que Python n’est pas installable sur la plupart des systèmes. Idem pour la portabilité. On peut installer GNU awk sans forcément se contraindre à POSIX.
Le script Gawk ci-dessous remplace entièrement le pipeline.
#!/usr/bin/env -S gawk -f
BEGIN {
FPAT = "\\[[^]]+\\]|\"[^\"]+\"|[^ ]+"
}
$6 == 500 {
count[$1]++
}
END {
PROCINFO["sorted_in"] = "@val_num_desc"
for (ip in count) {
print count[ip], ip
}
}
Script Python « jetable » généré par ChatGPT
#!/usr/bin/env python3
import re
from collections import Counter
p = re.compile(r'\[[^]]+\]|"[^"]+"|[^ ]+')
c = Counter()
with open("access.log", encoding="utf-8", errors="ignore") as f:
for line in f:
f = p.findall(line)
if len(f) > 5 and f[5] == "500":
c[f[0]] += 1
for ip, n in c.most_common():
print(n, ip)
Ne va pas me faire croire que Python n’est pas installable sur la plupart des systèmes. Idem pour la portabilité. On peut installer GNU awk sans forcément se contraindre à POSIX
Python n’est pas toujours installable sur ton environnement : pas la permission, pas disponible, ressources limités, connexion Internet non disponible. Et tous les systèmes n’utilisent pas les outils GNU.
Cette remarque n’est d’ailleurs pas artificielle : les systèmes embarqués peuvent ne pas avoir Python par faute de ressources manquantes (genre un RPi Zero 1ère génération) ou alors un vieux serveur AIX qui sert en production n’a pas forcément de version de Python disponible. Or, ils auront awk, sed, grep and co.
Encore une fois, le but n’est pas de dire que tu as tord, mais ta solution n’est pas adaptée à toutes les situations. Le but du jeu est de connaître des solutions, pour être versatile et avoir moins peur en terres inconnues. Se reposer sur une seule solution “parce que c’est mieux” est une fausse bonne idée. Et c’est clairement pas quelque chose que ChatGPT va nous apprendre !
Un pipeline Shell peut être écrit en quelques secondes.
Le problème est la fortuité. On finit par chercher des variantes pour coller au mieux au résultat souhaité. Cela entraîne un surcoût temporel inattendu pour un résultat plus ou moins satisfaisant. Ce processus semble facile en apparence mais il s’avère souvent tortueux.
Ce qui est souvent présenté comme une qualité universelle du Shell s’apparente également à l’un de ses principaux défauts. On vante l’approche Unix — « un outil qui fait une chose et qui le fait bien » — mais ce principe est paradoxalement mis à mal par la profusion d’utilitaires aux fonctions parfois très proches.
Bha pourtant dans Python tu as quinze milles libs qui font sensiblement la même chose, en plus tu peux pas les avoir en même temps, faut faire des environnements virtuels. Pas vraiment sûr que cet argument soit valable. En plus, à chaque montée en version t’es pas sûr que ça pète pas…
Non, c’est surtout que TU es plus à l’aise avec python et tant mieux :-)
Ce qui est désagréable, c’est qu’un problème simple génère une multitude de solutions en ligne de commande, toutes différentes, souvent imprécises, incorrectes ou redondantes.
Cela renvoie une image trompeuse de la ligne de commande avec des biais significatifs dans la description. Mais apparemment cela perdure.
Cette inefficacité remarquable à programmer en Shell apparaît nettement dans cet exemple. On entremêle succinctement des utilitaires de façon erratique. Le Shell est décrit comme étant un outil commode : courant, pratique et fiable.
Mais comment expliquer les multiples solutions insatisfaisantes sensées résorber le problème ? Si vous ne me croyez pas, il suffit de consulter des solutions sur Stack Exchange.
La ligne de commande semble convenir à première vue. Finalement, ce n’est pas aussi simple qu’escompté. On éprouve toute cette complexité en ressortant avec des commandes tortueuses. Parcourir les manuels des utilitaires, expérimenter, recomposer à nouveau en cas d’échec. Pour quoi ? Déboucher sur une ligne de commande qui nous aurait pris un temps fou pour y parvenir.
Sérieusement, le Shell n’est pas le bon outil. On aurait pu obtenir le même résultat sans effort avec un programme Python.
Plusieurs remarques concernant ce commentaire :
“Le mieux est l’ennemi du bien”, comme dirait l’autre
Je suis partiellement d’accord sur le principe.
On peut certainement chaîner des commandes efficacement et obtenir un résultat valable. Mais cela représente une charge mentale non négligeable. Il faut bien comprendre les divers utilitaires ainsi que le fonctionnement du Shell.
On se croirait au début du XXIe siècle concernant la remarque artificielle sur la disponibilité des ressources. Ne va pas me faire croire que Python n’est pas installable sur la plupart des systèmes. Idem pour la portabilité. On peut installer GNU awk sans forcément se contraindre à POSIX.
Le script Gawk ci-dessous remplace entièrement le pipeline.
Script Python « jetable » généré par ChatGPT
access.log fictif
Ouai bha c’est moins simple que le script shell du début ^__^ En plus c’est moins immédiat.
Python n’est pas toujours installable sur ton environnement : pas la permission, pas disponible, ressources limités, connexion Internet non disponible. Et tous les systèmes n’utilisent pas les outils GNU.
Cette remarque n’est d’ailleurs pas artificielle : les systèmes embarqués peuvent ne pas avoir Python par faute de ressources manquantes (genre un RPi Zero 1ère génération) ou alors un vieux serveur AIX qui sert en production n’a pas forcément de version de Python disponible. Or, ils auront awk, sed, grep and co.
Encore une fois, le but n’est pas de dire que tu as tord, mais ta solution n’est pas adaptée à toutes les situations. Le but du jeu est de connaître des solutions, pour être versatile et avoir moins peur en terres inconnues. Se reposer sur une seule solution “parce que c’est mieux” est une fausse bonne idée. Et c’est clairement pas quelque chose que ChatGPT va nous apprendre !
Rien qu’écrire cette ligne m’aurait pris plus de temps que de sortir :
Donc nope, désolé, pas d’accord avec
Un pipeline Shell peut être écrit en quelques secondes.
Le problème est la fortuité. On finit par chercher des variantes pour coller au mieux au résultat souhaité. Cela entraîne un surcoût temporel inattendu pour un résultat plus ou moins satisfaisant. Ce processus semble facile en apparence mais il s’avère souvent tortueux.
Ce qui est souvent présenté comme une qualité universelle du Shell s’apparente également à l’un de ses principaux défauts. On vante l’approche Unix — « un outil qui fait une chose et qui le fait bien » — mais ce principe est paradoxalement mis à mal par la profusion d’utilitaires aux fonctions parfois très proches.
On ne retrouve pas ces défauts dans Python.
Bha pourtant dans Python tu as quinze milles libs qui font sensiblement la même chose, en plus tu peux pas les avoir en même temps, faut faire des environnements virtuels. Pas vraiment sûr que cet argument soit valable. En plus, à chaque montée en version t’es pas sûr que ça pète pas…
Non, c’est surtout que TU es plus à l’aise avec python et tant mieux :-)
J’en conviens.
Ce qui est désagréable, c’est qu’un problème simple génère une multitude de solutions en ligne de commande, toutes différentes, souvent imprécises, incorrectes ou redondantes.
Cela renvoie une image trompeuse de la ligne de commande avec des biais significatifs dans la description. Mais apparemment cela perdure.
Différents chemins mènent à Saint-Bauzille-de-Putois. :o)