1. 5
  1.  

  2. 1

    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.

    1. 4

      Plusieurs remarques concernant ce commentaire :

      • 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

      1. 1

        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.

        #!/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)
        

        access.log fictif

        192.168.1.10 - - [10/Jun/2026:08:15:23 +0200] "GET /index.html HTTP/1.1" 200 5120
        203.0.113.45 - - [10/Jun/2026:08:16:01 +0200] "POST /api/login HTTP/1.1" 500 721
        198.51.100.12 - - [10/Jun/2026:08:16:15 +0200] "GET /products HTTP/1.1" 200 8342
        203.0.113.45 - - [10/Jun/2026:08:17:03 +0200] "POST /api/login HTTP/1.1" 500 721
        192.168.1.10 - - [10/Jun/2026:08:17:55 +0200] "GET /contact HTTP/1.1" 404 1204
        198.51.100.34 - - [10/Jun/2026:08:18:42 +0200] "GET /checkout HTTP/1.1" 500 913
        203.0.113.45 - - [10/Jun/2026:08:19:08 +0200] "GET /dashboard HTTP/1.1" 500 1102
        198.51.100.34 - - [10/Jun/2026:08:19:54 +0200] "POST /checkout HTTP/1.1" 500 913
        203.0.113.88 - - [10/Jun/2026:08:20:11 +0200] "GET /reports HTTP/1.1" 200 6543
        198.51.100.34 - - [10/Jun/2026:08:20:47 +0200] "GET /checkout HTTP/1.1" 500 913
        192.0.2.77 - - [10/Jun/2026:08:21:12 +0200] "GET /admin HTTP/1.1" 500 1500
        203.0.113.45 - - [10/Jun/2026:08:21:44 +0200] "GET /dashboard HTTP/1.1" 500 1102
        198.51.100.12 - - [10/Jun/2026:08:22:08 +0200] "GET /products HTTP/1.1" 200 8342
        192.0.2.77 - - [10/Jun/2026:08:22:33 +0200] "POST /admin HTTP/1.1" 500 1500
        198.51.100.34 - - [10/Jun/2026:08:23:01 +0200] "GET /checkout HTTP/1.1" 200 3400
        203.0.113.45 - - [10/Jun/2026:08:23:45 +0200] "GET /dashboard HTTP/1.1" 500 1102
        
        
        1. 4

          Ouai bha c’est moins simple que le script shell du début ^__^ En plus c’est moins immédiat.

          1. 2

            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 !

            1. 2
              FPAT = "\\[[^]]+\\]|\"[^\"]+\"|[^ ]+"
              

              Rien qu’écrire cette ligne m’aurait pris plus de temps que de sortir :

              grep “ 500 “ access.log | awk ‘{print $1}’ | sort | uniq -c | sort -rn

              Donc nope, désolé, pas d’accord avec

              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.

              1. 1

                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.

                1. 2

                  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 :-)

                  1. 1

                    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.

          2. 1

            Différents chemins mènent à Saint-Bauzille-de-Putois. :o)