Journal bake : scripter en bash à la « makefile »

Posté par  (site web personnel) . Licence CC By‑SA.
Étiquettes :
12
14
nov.
2025

Sommaire

Avant propos

make

Make est un bon outil et je me suis inspiré de la lecture de ce manuel pour concevoir l'exemple.

Pourquoi bash ?

Depuis que je code en entreprise et à la maison, sous linux/BSD autant que windows j'ai toujours eu accès à bash et aux GNU coreutils.

Quand vous installez git for windows vous installez plus que bash, vous installez, les Core Utils (dont mount et chroot), vous avez un tty (celui de mingw qui est un peu buggué), une arborescence de système linux, ssh, sftp, perl, make (oui), tk/tcl … ET VIM \o/

Tout ce qu'il faut pour bootstrapper un environnement à la linux surtout si vous ajoutez dans la soupe un gestionnaire de paquet que ce soit scoop ou (je n'ai pas essayé) pkgsrc

Bash est devenu ipso facto grâce à l'installation de git sur windows la stack de dév. pour un devops la plus portable. Le truc qui rappelle l'informatique des années Commodore 64, où partout où l'on arrive on trouve une invite pour coder standardisée.

Bake le design

Quand j'ai regardé le tuto de make j'ai vu le pattern qui me plaisait: une série de description :

  • état actuel, qui produit un artefact
  • une liste de dépendance pour arriver à l'état
  • un corps de « code » qui permet de faire la transition à l'état suivant.

par contre, chose qui me déplaît les artefacts de dépendances ne peuvent pas être genre des ports tcp ouverts (ex: si port 53 pas ouvert alors démarrer DNS).

J'ai décidé de faire une projection de make en bash avec une pile d'appel que l'on manipule explicitement.

Voici le code dont le cœur qui nous intéresse est à la ligne 53

#!/usr/bin/env bash
set -e
declare -a action;
RD='\e[31m'
GB='\e[33m'
BL='\e[34m'
RZ='\e[0m'

DEBUG=${DEBUG:-1}
ONE_VAR=${ONE_VAR:-template.dot}

echo -e "${GB}REPRODUCIBLE BUILD WITH"
echo -e      "-----------------------$RZ"
echo
for var in DEBUG ONE_VAR;
do
     printf "%s='%s' " "$var" "$( eval eval echo \\$\$var)"
done
echo -n $0 $@
echo
echo

d() {
    [ -z "$DEBUG" ] || echo -e "DEBUG:$(date +"%H:%M:%S"):$BL $* $RZ"
}

[ -d out ] || mkdir out


push() {
    local stack
    declare -a stack
    stack=( "$@" )
    for ((i=${#@}; i--; i)); do
        action=( "${stack[$i]}" "${action[@]}" );
    done
}


pop() {
    declare -n v=$1
    v=${action[0]}
    action=("${action[@]:1}")
}

set +x
dispatch_action() {
    while [[ ${#action} -gt 0 ]]; do
        pop act

        d "DISPATCHING $act"
        case $act  in
            all)
                [ -f out/this ] || push "before" ; dispatch_action
                touch out/that
                d all bells and whistles
                push "clean" ; dispatch_action
            ;;
            before)
                [ -f out/init ] || push init; dispatch_action
                d after init before all and clean
                touch out/this
            ;;
            init)
                d init : begin all
                touch out/init
            ;;
            clean)
                d clean everything
                set +e
                d out/*
                rm out/*
                set -e
            ;;
            *)
            echo unrecognized "$act";
                d "${action[@]}"
            break
            ;;
        esac
    done
}
if [ ! -z $1 ]; then
    action=( "$@" );
else
    push "all"
fi
dispatch_action
d fin

Le cœur de faire son makefile à la bash consiste à peupler le switch case des états qu'on veut, en prélude de faire ses tests de prérequis et pousser/appeler la boucle de dispatch si nécessaire, puis exécuter son code.

L’exemple ci dessus donne les sorties suivantes :

$ ./make.bash all
REPRODUCIBLE BUILD WITH
-----------------------

DEBUG='1' ONE_VAR='template.dot' ./make.bash all

DEBUG:10:08:50: DISPATCHING all 
DEBUG:10:08:50: DISPATCHING before 
DEBUG:10:08:50: DISPATCHING init 
DEBUG:10:08:50: init : begin all 
DEBUG:10:08:50: after init before all and clean 
DEBUG:10:08:50: all bells and whistles 
DEBUG:10:08:50: DISPATCHING clean 
DEBUG:10:08:50: clean everything 
DEBUG:10:08:50: out/init out/that out/this 
DEBUG:10:08:50: fin 

Ce qui est ce qu'on attend d'un make all

Maintenant faisons un make before puis un make all

$ ./make.bash all
REPRODUCIBLE BUILD WITH
-----------------------

DEBUG='1' ONE_VAR='template.dot' ./make.bash all

DEBUG:10:10:20: DISPATCHING all 
DEBUG:10:10:20: all bells and whistles 
DEBUG:10:10:20: DISPATCHING clean 
DEBUG:10:10:20: clean everything 
DEBUG:10:10:20: out/init out/that out/this 
DEBUG:10:10:20: fin 

on a bien la propriété des makefiles de ne pas refaire une étape si la dépendance est ouverte

Limites et avantages de l'approche

les wildcards

Si un truc vous manque de make et que c'est les jokers (wildcard) alors cet outil n'est pas fait pour vous ; je ne vois absolument pas comment coder facilement cette fonctionnalité.

pousser des actions futures

En make on ne peut que déclarer les dépendances ici, on peut (voir all) pousser des actions futures. Je suis sûr que c'est une mauvaise idée, mais c'est faisable.

les makes récursifs

Je ne me suis pas penché sur le problème, mais je crois bien que cette fonctionnalité ne m'est pas accessible :)

Conclusion

En résumé, bash n'est pas qu'un shell, c'est aussi un environnement de programmation.

La Gnu/Basherie ultime que déteste la secte concurrent de la mienne qu'est le POSIX-shismes ce sont les tableaux.

Et pourtant avoir des tableaux (dont associatifs) permet de faire des chouettes trucs en bash (voir les primitives push et pop).

La programmation ce n'est pas que sortir un résultat avec un langage bien branlé, c'est aussi s'en sortir avec un langage bringuebalant.

  • # un exemple de la vraie vie

    Posté par  (site web personnel) . Évalué à 2 (+1/-0).

    • [^] # Re: un exemple de la vraie vie

      Posté par  . Évalué à 4 (+2/-0).

      bash -e -u est une bonne pratique.

      Et dans ce cas, pour explicitement ignorer une erreur, si la commande ne le permet pas (pas d'option quiet), au lieu de

                  set +e
                  rm out/*
                  set -e

      j'aime bien

                  rm out/* || true

      Ça fait moins de lignes, donc moins de risque d'erreurs, du style, inverser les "+" et "-", oublier une des deux lignes, au hasard celle qui stop après une erreur.

  • # le langage est bash, donc le langage est bash

    Posté par  (site web personnel, Mastodon) . Évalué à 10 (+9/-2). Dernière modification le 14 novembre 2025 à 14:42.

    Bash est devenu ipso facto grâce à l'installation de git sur windows la stack de dév. pour un devops la plus portable.

    Oui, sous Windows et Linux, c’est maintenant très proche.

    Mais pas sous macOS, qui a un bash de 2007, qui est très primitif, et c’est un enfer. Par exemple si ma mémoire est bonne, utiliser "${@}" dans une fonction avec set -u déclenche l’arrêt de l’exécution si la fonction est appelée sans paramètre, au lieu de retourner un tableau vide. Puisque tu parles de make, leur make est tout aussi ancien, quasiment 20 ans, et ça peut te planter un couteau dans le dos quand tu ne t’y attends pas.

    La Gnu/Basherie ultime que déteste la secte concurrent de la mienne qu'est le POSIX-shismes ce sont les tableaux.

    Utiliser bash dans un script bash ce n’est pas sectaire. La secte c’est de réclamer que tout programme soit polyglotte.

    Ça m’est insupportable quand j’écris un programme en choisissant bash comme langage et en mettant comme shebang #! /usr/bin/env bash et quelqu’un vient et propose un pull-request sabotant tout le code, le transformant de manière très alambiqué et fragile pour le rendre polyglotte avec d’autres langages.

    Il est tout autant légitime d’écrire un programme en langage bash qu’il est légitime d’écrire une programme en langage python ou ruby. Ton script est écrit en bash, pas en posix-shell. Utiliser un autre interpréteur pour l’exécuter est une faute de l’utilisateur, pas la tienne. Ton script déclare explicitement que bash doit être utilisé pour l’interpréter, tout système qui utiliserait un autre interpréteur pour un autre langage serait en faute, et le bug ne serait pas à rapporter à toi mais à celui qui a implémenté l’usage d’un autre interpréteur que bash pour bash sur son système.

    Je sais pas comment font les développeurs de bash à savoir que depuis plus de 35 ans tout leur travail est systématiquement dénigré, diffamé, et rejeté par une secte de fanatiques du script polyglotte qui ont fait de leur trouble obsessionnel compulsif à ne jamais utiliser une seule contribution des développeurs de bash un code moral absolu. T’imagines tu développe pendant 35 ans un langage pour simplifier la vie des gens et t’as des gens qui font tout pour ne jamais en profiter car ce serait péché ?

    Personnellement j’aime bien écrire des scripts polyglottes pour le défi (je pourrai écrire un journal sur l’un d’eux, d’ailleurs), mais je ne vais pas me plaindre auprès d’un tiers parce qu’un script bash utilise le langage bash… Ce serait aussi stupide que se plaindre qu’un script python est écrit en python et ne fonctionne pas avec l’interpréteur ruby…

    Ah, au fait, une partie de la secte soit-disant POSIX qui réclame de saboter les scripts bash est en fait la secte de fanboy macOS sous couverture qui redirige sa souffrance causée par la faillite d’Apple à fournir des outils à jour envers tout le reste du monde pour ne pas regarder en face la relation abusive dans laquelle il est enfermé, qui ne peut briser son déni d’être victime d’un abuseur qui l’enferme dans une relation amour-haine qui le détruit, et qui fait payer à tout les autres cette souffrance pour protéger son abuseur.

    ce commentaire est sous licence cc by 4 et précédentes

    • [^] # Re: le langage est bash, donc le langage est bash

      Posté par  (site web personnel) . Évalué à 10 (+9/-0).

      Chouette description d'une partie des réelles quolibets auxquels un dev bash fait face dans le monde réel. C'est limite du sectarisme.

      Il n'y a pas qu'une pureté dans le code malheureusement, il y a aussi dans les outils, et parfois certains préfèrent des « stacks » toutes prêtes même si en tant qu'artisan/ouvrier, le propre de notre métier est d'être capable de construire nos propres outils de se les approprier.

      illustration

    • [^] # Re: le langage est bash, donc le langage est bash

      Posté par  (Mastodon) . Évalué à -3 (+2/-8). Dernière modification le 15 novembre 2025 à 13:50.

      Un programme python ou ruby a par convention son extension propre. Ta remarque serait valide si les gens qui écrivent des script bash non posix compatible utilisaient une extension .bash au lieu de .sh. Il y a plein de cas où le script n'est pas executé depuis un shell et donc un interpréteur est ajouté devant lui. Quand c'est un .sh il est raisonnable de penser qu'il puisse être executé via un shell compatible bourne shell, d'autant plus que bash n'est pas installé partout, spécialement dans des conteneurs ou dans l'embarqué. Quelqu'un qui écrit un script pour fish le nomme en général exemple.fish, idem ça se voit moins maintenant mais c'était le cas pour les scripts .csh ou .ksh respectivement pour les C et Korn shells et là il n'y a pas d'ambiguïté.

      Alors oui on peut vérifier le shebang (quand il existe car il n'est pas obligatoire) ou le code avant, et non une extension n'est pas obligatoire dans un fichier, mais comme dans toute société qui fonctionne à peu près bien on s'est habitué à cette convention d'utiliser des extensions pour identifier les types de fichiers et je ne vois pas pourquoi les bashiens ne feraient pas pareil et devraient se comporter comme des antisociaux qui font chier juste pour le plaisir de faire chier juste parce qu'ils ont gagné une ridicule et petite bataille de popularité sur un OS en particulier.

      Bref, nommez vos scripts bash .bash et plus personne n'a de raison de se plaindre et vous pouvez arrêter de vous poser en victime derrière vos attitudes toxiques.

      • [^] # Re: le langage est bash, donc le langage est bash

        Posté par  (site web personnel) . Évalué à 7 (+5/-0).

        Ou ne mettez pas d'extension. Ça ne sert à rien une extension sur un exécutable.

        • [^] # Re: le langage est bash, donc le langage est bash

          Posté par  (Mastodon) . Évalué à 3 (+0/-0). Dernière modification le 16 novembre 2025 à 11:29.

          Remarque très valide si le seul et unique but c'est de lui donner un droit d'execution et de passer par le shebang.

          • [^] # Re: le langage est bash, donc le langage est bash

            Posté par  (site web personnel, Mastodon) . Évalué à 3 (+1/-0).

            Genre tu veux faire monsupershell chemin/levilainscript.sh et espérer ne pas passer par le shebang ? Ça marche vraiment chez toi ?

            “It is seldom that liberty of any kind is lost all at once.” ― David Hume

            • [^] # Re: le langage est bash, donc le langage est bash

              Posté par  (Mastodon) . Évalué à 3 (+0/-0).

              Ben oui c'est toujours le cas. Fait le test avec un bashisme et un shell qui ne le comprend pas pour t'en convaincre.

              $ cat script_bash.sh 
              #!/usr/bin/env bash
              i=1
              ((i++))
              echo $i
              
              
              $ ./script_bash.sh 
              2
              
              
              $ dash ./script_bash.sh 
              ./script_bash.sh: 3: i++: not found
              1
              • [^] # Re: le langage est bash, donc le langage est bash

                Posté par  (site web personnel, Mastodon) . Évalué à 2 (+0/-0).

                L’exemple fonctionne avec zsh et ksh chez moi (donc un bashisme quasiuniversel ?) mais pas avec dash (seul mauvais élève que j’ai sous la main) :p Non, mais plus sérieusement, ça marche et je ne m’en étais pas rendu compte et je ne sais pas pourquoi les shells font cela :(

                $ cat toto.py
                #/usr/bin/python
                number = int(input())
                print(number * number)
                
                $ bash toto.py 
                toto.py: line 2: syntax error near unexpected token `('
                toto.py: line 2: `number = int(input())'

                “It is seldom that liberty of any kind is lost all at once.” ― David Hume

                • [^] # Re: le langage est bash, donc le langage est bash

                  Posté par  (Mastodon) . Évalué à 3 (+0/-0).

                  Ce n'est pas un bashisme exclusif on va dire.

                  Au contraire c'est bien que le shebang ne soit pas utilisé quand tu spécifies un interpréteur, ça te permet de pouvoir tester une version différente poyr oar exemole tester une nouvelle version d'un language de programation, vérifier un bug sur une autre version, etc sans devoir éditer tous tes fichiers. Il faut garder en tête que ce n'est pas exclusif au shells.

                  • [^] # Re: le langage est bash, donc le langage est bash

                    Posté par  (site web personnel) . Évalué à 3 (+0/-0). Dernière modification le 18 novembre 2025 à 10:53.

                    https://www.in-ulm.de/~mascheck/various/shebang/
                    https://en.wikipedia.org/wiki/Shebang_%28Unix%29

                    Si tu fais un_executable_quelconque un_script_avec_une_shebang, alors un_executable_quelconque est exécuté avec comme argument un_script_avec_une_shebang et il en fait ce qu'il doit (que l'on parle de wc, de gcc, de python, de gimp ou de systemctl comme exécutable quelconque). Éventuellement s'il ne comprend rien à l'argument, par exemple si on donne un bout de code en C à gimp en argument, il ne va rien en faire d'utile.
                    Si tu fais un_script_avec_une_shebang, alors la shebang est détectée et c'est l'interpréteur/exécutable décrit ensuite qui sera utilisé pour exécuter le script. De même il faut que l'interpréteur soit compatible avec le script en question, ça ne marchera pas mieux avec #!/usr/bin/gimp si la suite est un bout de code C.
                    Comme dit précédemment, ce n'est pas exclusif aux shells.

                    • [^] # Re: le langage est bash, donc le langage est bash

                      Posté par  (site web personnel) . Évalué à 3 (+0/-0).

                      Exemples :

                      ==> /bin/instmodsh <==
                      #!/usr/bin/perl
                      --
                      ==> /bin/istanbul <==
                      #!/usr/bin/env node
                      
                      ==> /bin/krb5-config <==
                      #!/bin/sh
                      
                      ==> /bin/ldd <==
                      #!/bin/bash
                      
                      ==> /bin/lwp-dump <==
                      #!/usr/bin/perl
                      
                      ==> /bin/mactime <==
                      #!/usr/bin/perl -w
                      
                      ==> /bin/pdb3.13 <==
                      #! /usr/bin/python3.13
                      
                      ==> /bin/zsh5 <==
                      #!/bin/zsh -f
                      
                      • [^] # Re: le langage est bash, donc le langage est bash

                        Posté par  (site web personnel, Mastodon) . Évalué à 2 (+0/-0).

                        Je pense que nous sommes tous les deux d’accord avec toi :) C’est juste que Psychofox nous disait rajouter l’interpréteur devant les *.sh et que je m’étonnais que les shells ne tiennent pas compte de l’entête magique (que les langages de scripting ne le fassent pas ne m’étonne pas, mais je m’attendais à mieux de la part du shell qui par essence lance des commandes… mais là il lit un fichier et en applique le contenu comme les autres langages de script —finalement cohérent même si ce n’est pas ce que j’imaginais)
                        Il parait que ça peut servir pour tester ; et sinon mes scripts sont toujours exécutables et peuvent porter n’importe quoi comme extension ou ne pas en avoir (on n’est pas chez ms…)

                        “It is seldom that liberty of any kind is lost all at once.” ― David Hume

                        • [^] # Re: le langage est bash, donc le langage est bash

                          Posté par  (Mastodon) . Évalué à 3 (+0/-0).

                          je dis juste que si tu mets l'interpréteur devant le nom du script, qu'il ait un shebang ou pas, qu'il soit executable ou pas il sera executé par cet interpréteur.

                          ~/src $ cat toto.py
                          #!/usr/bin/env python
                          
                          print('Hello, World!')
                          ~/src $ chmod +x toto.py
                          ~/src $ ./toto.py
                          Hello, World!
                          ~/src $ /bin/sh toto.py
                          toto.py: 3: Syntax error: word unexpected (expecting ")")
                          

                          Et c'est très bien comme cela!

                          Je ne te dis pas ce que tu dois faire ni comment tu dois nommer tes fichiers persos sur ta machine :)

                          Quand tu distribues des fichiers, c'est bien de s'assurer que ce qui est du bash (c'est pareil pour du zsh ou autre) soit documenté, et qu'utiliser l'extension .sh est selon moi une mauvaise pratique et devrait se limiter aux scripts de type bourne shell portables. Et c'est vrai que si on veut être bon citoyen numérique et distribuer une application portable et pas limitée à Linux, ça fait pas de mal de rester sur du posix, une norme c'est fait pour ça même si c'est limitant. Ce n'est pas compliqué d'installer bash mais c'est une dépendance supplémentaire à gérer pour un gain assez négligeable dans l'écriture d'un script la plupart du temps.

                          • [^] # Re: le langage est bash, donc le langage est bash

                            Posté par  (Mastodon) . Évalué à 1 (+0/-0).

                            Le souci vient peut-être aussi d'une notion de système de base qui n'existe pas vraiment sous Linux, contrairement aux BSD (et d'autres) ou les applications sont vues comme des apports extérieurs, et où donc installer bash, revient à ajouter une pièce rapportée qui n'est pas partie prenante de l'OS par défaut.
                            En tout cas ta dernière remarque me fait penser à ça, je n'ai pas l'impression que beaucoup d'admins de machines Linux pensent de cette façon.

                          • [^] # Re: le langage est bash, donc le langage est bash

                            Posté par  (site web personnel, Mastodon) . Évalué à 4 (+3/-1). Dernière modification le 20 novembre 2025 à 01:35.

                            Y a pas méprise là ?

                            Quand tu distribues des fichiers, c'est bien de s'assurer que ce qui est du bash (c'est pareil pour du zsh ou autre) soit documenté, et qu'utiliser l'extension .sh est selon moi une mauvaise pratique et devrait se limiter aux scripts de type bourne shell portables.

                            L’extension pour bash et ksh a justement toujours été .sh aussi loin que j’ai pu remonter. Tu es juste en train de vouloir imposer ta pratique… :)
                            Et l’expérience montre que la meilleure distribution de scripts est avec les permissions +x et le shebang.

                            “It is seldom that liberty of any kind is lost all at once.” ― David Hume

                          • [^] # Re: le langage est bash, donc le langage est bash

                            Posté par  . Évalué à 4 (+2/-0).

                            Et c'est vrai que si on veut être bon citoyen numérique et distribuer une application portable et pas limitée à Linux, ça fait pas de mal de rester sur du posix, une norme c'est fait pour ça même si c'est limitant.

                            D'une part ça dépend de ce que tu entends par distribue. Si je veux faire comme toi et pousser les contraintes, je dirais que si tu veux être un bon citoyen numérique tu paquage ce que tu distribue donc tu t'adapte a tes plate-forme cible. C'est mieux pour tes utilisateurs Mac que tu ai distribué via brew (même si tu as ajouté la dépendance bash 5 qui sera géré par brew) que de s'être limité à POSIX (dans la syntaxe et dans les utilitaires) mais que tu fournisse qu'un gist jamais mis à jour pas versionné.

                            Ensuite il faut pas s'ajouter du travail pour le principe. L'énorme majorité des scripts qu'on écrit ne sortiront jamais de nos machines

                            https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

                    • [^] # Re: le langage est bash, donc le langage est bash

                      Posté par  (site web personnel) . Évalué à 4 (+1/-0). Dernière modification le 18 novembre 2025 à 11:21.

                      Pour le plaisir du chipotage, gimp ouvre le code C décrit comme XPM 3 sur https://en.wikipedia.org/wiki/X_PixMap (et gcc lit le XPM 1 et 3 sans rien en faire de palpitant si utilisé seul).

                      Toi aussi exécutes tes images :

                      $ cat ./xpm3.xpm
                      #!/usr/bin/env gimp
                      /* XPM */
                      static char * XFACE[] = {
                      "48 4 2 1",
                      "a c #ffffff",
                      "b c #000000",
                      "abaabaababaaabaabababaabaabaababaabaaababaabaaab",
                      "abaabaababaaabaabababaabaabaababaabaaababaabaaab",
                      "abaabaababaaabaabababaabaabaababaabaaababaabaaab",
                      "abaabaababaaabaabababaabaabaababaabaaababaabaaab"
                      };
                      $ ./xpm3.xpm
                      Gtk-Message: 11:19:39.921: Failed to load module "canberra-gtk-module"
              • [^] # Re: le langage est bash, donc le langage est bash

                Posté par  (site web personnel, Mastodon) . Évalué à 4 (+1/-0). Dernière modification le 18 novembre 2025 à 23:47.

                C’est toujours le cas car c’est ce qui est demandé.

                $ cat script-python
                #! /usr/bin/env python2
                print "bonjour tout le monde"
                
                $ ./script-python
                bonjour tout le monde
                
                $ python2 script-python
                bonjour tout le monde
                
                $ python3 script-python
                  File "script-python", line 2
                    print "bonjour tout le monde"
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)?
                
                $ ruby script-python
                ruby: no Ruby script found in input (LoadError)
                

                C’est le shebang qui détermine l’interpréteur, à moins que l’utilisateur ne force un autre.

                Ce n’est pas qu’une affaire de script, c’est vrai aussi pour le code compilé:

                
                $ file /usr/bin/whoami
                /usr/bin/whoami: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=064a1abc92933fda978fa7d97250c1bf12c65e46, for GNU/Linux 3.2.0, stripped
                
                $ LANG=C.UTF-8 readelf -l /usr/bin/whoami | grep 'Requesting program interpreter'
                      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
                
                $ /usr/bin/whoami
                illwieckz
                
                $ /lib64/ld-linux-x86-64.so.2 /usr/bin/whoami
                illwieckz
                
                $ /usr/i686-linux-gnu/lib/ld-linux.so.2 /usr/bin/whoami
                /usr/bin/whoami: error while loading shared libraries: /usr/bin/whoami: wrong ELF class: ELFCLASS64
                
                $ /usr/aarch64-linux-gnu/lib/ld-linux-aarch64.so.1 /usr/bin/whoami
                /usr/bin/whoami: error while loading shared libraries: /usr/bin/whoami: cannot open shared object file: No such file or directory
                

                Ça veut d’ailleurs dire qu’on peut techniquement passer des paramètres dans le shebang:

                $ cat test
                #! /usr/bin/bash -x
                echo test
                
                $ ./test
                + echo test
                test
                

                Bon, mais ne faites pas ça, la façon standard d’appeler un interpréteur c’est /usr/bin/env <interpréteur>, et rajouter des paramètres risque de casser la détection du langage par les non-interpréteurs (comme les éditeurs pour activer la bonne coloration syntaxiques).

                Si vous ne renseignez pas l’interpréteur correctement les outils non-interpréteurs seront perdus car c’est ce qu’ils regardent, et le shebang est bien plus fiable que l’extension: il ne peut pas mentir. Le shebang est non-ambigu, ajouter une extension à un programme pensé pour être appelé depuis un shell, saymal:

                Ajouter une extension comme un .py c’est utile pour une bibliothèque par exemple, mais pour appeler une commande, ajouter une extension c’est très très mal. En dehors de ce genre de cas de bibliothèque, ajouter une extension à un script c’est généralement pour contourner les limitations de Windows qui ne regarde pas l’entête du fichier pour déterminer son format.

                Mais là encore, derrière le gang qui salit les scripts en y ajoutant des extensions, il y a un culte du cargo entretenus par ceux qui ont imité des Windowsiens, reproduisant par mimétisme les gestes sans comprendre pourquoi ces Windowsiens faisaient ainsi, Windowsiens pour qui ces rites participent en fait à leur stratégie d’évitement et de résilience face à la souffrance que Windows leur cause.

                ce commentaire est sous licence cc by 4 et précédentes

                • [^] # Re: le langage est bash, donc le langage est bash

                  Posté par  (site web personnel, Mastodon) . Évalué à 4 (+2/-0).

                  Décidément… Je suis de la team on met des options à l’interpréteur et le manpage de env m’indique

                  NAME
                       env – set environment and execute command, or print environment
                  
                  SYNOPSIS
                       env [-0iv] [-u name] [name=value ...]
                       env [-iv] [-P altpath] [-S string] [-u name] [name=value ...]
                           utility [argument ...]
                  

                  Pour les extensions ça sert effectivement à révéler les détails d’implémentation et servir d’aide mémoire (par exemple je sais que mon foo.tar.gz.enc a été taré puis gézippé et enfin passé dans la fonction de cryptage) pour les données (je mets pas d’extension à mes scripts car d’une part ils sont exécutables et d’autre part ce qui a commencé comme truc.bash peut devenir truc.perl demain et truc.go après-demain avec l’évolution des besoins.)

                  Quand à fenêtre, les extensions sont une vaste blague qui permettent de sacrés farces…

                  “It is seldom that liberty of any kind is lost all at once.” ― David Hume

                  • [^] # Re: le langage est bash, donc le langage est bash

                    Posté par  (site web personnel, Mastodon) . Évalué à 3 (+0/-0).

                    Oui, c’est tout à fait possible de mettre des arguments dans le shebang. Ici on pourrait faire #! /usr/bin/env -S bash -x

                    Personnellement j’ai fait ce genre de chose (mettre des arguments dans le shebang) dans le passé, mais maintenant j’évite quand c’est évitable. Je ne serai pas surpris si pour certains langages ce serait inévitable (par exemple pour spécifier comment le code doit être interprété avant que l’interprétation ne commence).

                    Utiliser des arguments dans le shebang peut avoir le mauvais effet de semer la confusion chez les éditeurs et autre logiciels qui veulent détecter le format du document (et non exécuter le code).

                    Dans l’exemple ci-dessus, si un logiciel cherche ^#![ ]*/usr/bin/env[ ]+bash pour détecter le langage bash pour activer la coloration syntaxique, ça ne marchera pas. Et détecter toute les variantes implique d’émuler une partie de env lui-même… je doute que tous les éditeurs soient aussi exhaustifs ! VIM a l’air de s’en sortir en tout cas.

                    Typiquement pour des options de bash comme -e, ça coûte rien de le mettre sur la ligne d’après si ça aide l’éditeur à correctement coloriser le code, mais ça n’est pas une question d’exécution. Le shebang est d’abord là que pour exécuter, et c’est en ça qu’il est fiable.

                    Je ne me suis pas exprimé sur les extensions de fichiers qui ne sont pas exécutables et qu’il faut bien reconnaître (surtout quand on pense à tous les formats qui utilise zip comme conteneur). L’extension n’est décisive pour l’exécution que sous Windows (.exe, .com, .cmd, .bat…), ailleurs on a un format standard pour dire au système quoi faire. 😎

                    ce commentaire est sous licence cc by 4 et précédentes

    • [^] # Re: le langage est bash, donc le langage est bash

      Posté par  (site web personnel) . Évalué à 3 (+1/-0).

      qui a un bash de 2007, qui est très primitif,

      Sale gamin !

      • [^] # Re: le langage est bash, donc le langage est bash

        Posté par  (site web personnel, Mastodon) . Évalué à 3 (+1/-0).

        Cela m’a intrigué et je suis allé vérifier (après avoir localisé celui du système vu que j’en ai un autre installé sur la bécane)

        $ bash --version
        GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin22)
        Copyright (C) 2007 Free Software Foundation, Inc.

        Ouch… Mais bon, ce n’est pas primitif (ce n’est pas l’interpréteur Almiquish ou Thomson hein), juste un peu vieux : la troisième génération alors qu’on est à la cinquième (le fameux deux trains de retard…?)

        “It is seldom that liberty of any kind is lost all at once.” ― David Hume

        • [^] # Re: le langage est bash, donc le langage est bash

          Posté par  (site web personnel, Mastodon) . Évalué à 7 (+4/-0).

          Je crois que la raison de cette obsolescence, c’est qu’ils s’interdisent tout ce qui est GPLv3.

          Et de manière générale ils préfèrent quand il y n’y a pas de copyleft.

          Mais ils sont bien obligés de fournir un bash et un GNU make à cause d’à quel point ça domine, mais ils fournissent un bash et un GNU make du début du siècle.

          Mais rien ne devrait les empêcher de corriger le bug du tableau vide considéré comme une variable inexistante… Ça c’est, de mon expérience, le bug le plus handicapant du bash de macOS.

          Un bash avec une implémentation incomplète des tableaux, c’est un bash primitif.

          ce commentaire est sous licence cc by 4 et précédentes

      • [^] # Re: le langage est bash, donc le langage est bash

        Posté par  (site web personnel, Mastodon) . Évalué à 5 (+3/-0).

        Puisque tu parles de make, leur make est tout aussi ancien, quasiment 20 ans, et ça peut te planter un couteau dans le dos quand tu ne t’y attends pas.

        Je suis allé vérifier aussi

        $ make --version
        GNU Make 3.81
        Copyright (C) 2006  Free Software Foundation, Inc.
        This is free software; see the source for copying conditions.
        There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
        PARTICULAR PURPOSE.
        
        This program built for i386-apple-darwin11.3.0
        
        $ echo $((2025-2006)) ans
        19 ans

        Après, pour l’attaque à l’arme blanche, je ne me prononce pas.

        “It is seldom that liberty of any kind is lost all at once.” ― David Hume

        • [^] # Re: le langage est bash, donc le langage est bash

          Posté par  (site web personnel) . Évalué à 3 (+1/-0).

          Je serais curieux des killers features introduites ans make (voire bash) ces 20 dernières années.

          Adhérer à l'April, ça vous tente ?

          • [^] # Re: le langage est bash, donc le langage est bash

            Posté par  (site web personnel) . Évalué à 1 (+0/-0).

            je viens de découvrir coproc introduit en bash 4 dont je ne vois pas l'utilité.

            https://copyconstruct.medium.com/bash-coprocess-2092a93ad912

          • [^] # Re: le langage est bash, donc le langage est bash

            Posté par  (site web personnel, Mastodon) . Évalué à 4 (+1/-0).

            Aucune idée, mais notre implémentation de “Pre-Compiled Header” avec CMake et le backend “GNU Make” fonctionnait partout où il y a GNU Make sauf sur le GNU Make de macOS. Le dysfonctionnement avait tout les symptômes d’un bug ou d’une déficience dans l’échappement de chaînes de caractères. Maintenant que CMake a un méchanisme intégré pour faire du PCH on l’utilise, et ça marche pour le GNU Make de macOS, je ne serai pas surpris si CMake faisait des contournements spécifiques pour macOS…

            ce commentaire est sous licence cc by 4 et précédentes

          • [^] # Re: le langage est bash, donc le langage est bash

            Posté par  (site web personnel, Mastodon) . Évalué à 4 (+2/-0).

            Il y a quelques mois, un script que j’avais pondu sans savoir l’état du parc est remonté en erreur sur quelques machines et après investigation il se trouvait que ce sont seulement les machines avec GNU bash, version 3.00.15(1)-release (i386-redhat-linux-gnu) et GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu) qui plantaient avec le script.

            L’une des erreurs était liée à l’utilisation des expressions rationnelles avec les tests, chose que je tenais pour acquise ; mais après investigation il se trouve que c’est possible seulement à partir la version 3.1+

            # help asked?
            -if [[ $1 =~ ^-(h|-help)$ ]]; then
            +if [[ $1 == '-h' || $1 == '--help' ]]; then
                display_help
            
            …
            
            # not an integer
            -if ! [[ $1 =~ ^[0-9]+$ ]]; then
            +if ! [ "$1" -eq "$1" 2>/dev/null ]; then

            ou plutôt ça dépend des cas, et pour les entiers ça manquait un peu de cohérence.
            Il y a aussi une grosse portion du script que j’ai du réécrire car m’étant appuyée sur shopt qui n’était pas disponible.

            On peut trouver les évolutions dans les annonces/NEWS en ligne ou en local dans les bonnes crémeries

            “It is seldom that liberty of any kind is lost all at once.” ― David Hume

            • [^] # Re: le langage est bash, donc le langage est bash

              Posté par  (site web personnel, Mastodon) . Évalué à 4 (+1/-0).

              Personnellement je ne demande pas grand chose à bash, je sous-utilises ses capacités avancées en fait, mais certaines fonctionnalités sont vraiment pratiques, comme les array.

              Je veux pouvoir faire ça, et itérer tout ça :

              vars=("un deux" blabla)
              for var in "${var[@]}"
              do
                echo "${var}"
              done

              Utiliser des hacks comme ça, ça ne marche pas:

              vars='un deux blabla'
              for var in ${vars}
              do
                echo "${var}"
              done

              Et ça, c’est dégueulasse et ça invoque des bugs les soirs de pleine-lune :

              vars="un deux
              blabla"
              cat "${vars}" | while read "${var}"
              do
                echo "${var}"
              done

              Oui je sais on peut aussi modifier IFS, mais bref, tout ça c’est moche et ce sont des nids à problèmes.

              Le code de tableau ci-dessus fonctionne sous macOS parce que c’est un exemple très limité, mais dès qu’on passe un tableau en paramètre à une fonction, tout s’écroule.

              Ça, ça ne marge pas avec le bash de macOS :

              func()
              {
                for var in "${@}"
                do
                  echo "${var}"
                done
              }
              
              vars=()
              
              if "${something}"
              then
                vars+=("blabla")
              fi
              
              func "$[vars[@]}"

              Quand le tableau est vide, alors ${@} n’est pas déclarée dans la fonction, et donc le script s’interrompt à cause de la variable inconnue dès lors qu’on active set -u.

              On peut contourner en faisant quelque chose comme ça :

              func()
              {
                if -z "${@:-}"
                then
                  return
                fi
              
                for var in "${@}"
                do
                  echo "${var}"
                done
              }
              
              vars=()
              
              if "${something}"
              then
                vars+=("blabla")
              fi
              
              func "$[vars[@]}"

              Bon, j’ai écrit ce commentaire de mémoire, il y a peut-être encore de nuances obscures, et j’ai peut-être aussi fait des fautes, mais vous voyez l’idée. Il faut dégueulasser les scripts avec ce genre de contournements pour le bash de 2007 de macOS.

              ce commentaire est sous licence cc by 4 et précédentes

          • [^] # Re: le langage est bash, donc le langage est bash

            Posté par  (site web personnel, Mastodon) . Évalué à 4 (+2/-0).

            Dans Make proprement dit, il y a un standard qui n’a pas vraiment bougé à ma connaissance. Du coup, les fonctionnalités de la mort sont des ajouts propres aux différentes implémentations… Et gmake a ses fritures et donc des incompatibilités avec les autres !
            Quand j’ai du jongler, à une époque, entre les implémentations BSD et GNU une page de Chris Wellons (nullprogram) a rejoint mes favoris. Par contre, pas simple de tracer les ajouts de chaque implémentation ces deux dernières décennies.

            “It is seldom that liberty of any kind is lost all at once.” ― David Hume

          • [^] # Re: le langage est bash, donc le langage est bash

            Posté par  . Évalué à 3 (+1/-0).

            bash 4 avait apporté des trucs cool.

            • le globstar pour utiliser ** dans les expansions en interactif c’est très aggréable
            • les tableaux associatifs et ça c’est vraiment confortable par rapport à avoir un tableau de clefs et un tableau de valeurs
            • les braces expansions qui gèrent le 0 padding donc {02..24} c’est très agréable quand tu manipules des fichiers qui correspondent ou des heures

            https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

      • [^] # Re: le langage est bash, donc le langage est bash

        Posté par  (site web personnel, Mastodon) . Évalué à 6 (+3/-0). Dernière modification le 16 novembre 2025 à 23:30.

        J’ai rigolé, mais j’ai commencé à programmer en C K&R avec Lattice C (compilateur qui servira de base à Microsoft C 1), avec TED d’Information Builder comme éditeur (éditeur modal, mais au fonctionnement différent de VI) qui est bien plus ancien que edit.com, et en scriptant la compilation avec des .bat écrits pour le command.com de DOS 3.3. Ça m’amuse encore de jouer avec Lattice C de temps en temps, mais à ce niveau c’est pas de la programmation c’est du rétrogaming.

        Alors que quand je me prends dans la figure un bash de 2007 et un make de 2006 sur macOS, je ne joue pas du tout, ça ne m’amuse pas du tout, et c’est une vraie souffrance.

        Cette obsolescence est la raison pour laquelle on privilégie Python à Bash pour les scripts de développement du jeu Unvanquished, mais un langage de script c’est parfois plus pratique que Python, donc on en a quand même un ou deux et à chaque fois on doit dégueulasser le script avec des convolutions affreuses pour conserver la compatibilité avec le bash de 2007. Pour le coup, Apple nous empêche de bénéficier de toute avancée (fonctionnalité, correctif de bug) qui serait apparue dans bash depuis 2007… C’est du véritable sabotage pour les choses, et de la maltraitance pour les hommes.

        ce commentaire est sous licence cc by 4 et précédentes

  • # conflit avec WSL?

    Posté par  . Évalué à 2 (+1/-0).

    Le shebang #!/usr/bin/env bash il marche bien sur Windows chez toi?

    Sur les Windows au boulot, dès que WSL est installé, les scripts avec ce shebang lancent le bash de WSL dans le répertoire home de WSL. Résultat aucun script ne fonctionne correctement.
    Ça lance WSL, même quand on est déjà dans bash depuis l'invite de commande de commande de git-bash.

    C'est une vraie plaie.

    • [^] # Re: conflit avec WSL?

      Posté par  (site web personnel) . Évalué à 1 (+0/-0).

      Dans l'install de git for windows il y a un truc marqué comme dangereux pour changer le comportement de l'env et associé au .sh. Non ?

      Là, je suis aveugle, j'ai plus de windows sous la main, et git for windows ne s'installe pas avec wine.

      • [^] # Re: conflit avec WSL?

        Posté par  (site web personnel, Mastodon) . Évalué à 3 (+1/-0).

        Au moment de l’installation il faut vérifier qu’on n’a pas fait n’importe quoi avec les variables d’environnement ;
        fenêtre d’ajustement des variables d’environnement
        voir si l’on met l’option la plus restrictive (la première) et non la plus laxiste (la troisième et dernière) si le problème persiste.

        Et aussi, je pense que la console native permet plus de contrôle par le système hôte alors que l’alternative (que je préfère ne serait-ce pour ne pas avoir à me battre avec la configuration de l’encodage) n’est utilisé que par git-bash (en tout cas pas par WSL)
        fenêtre de choix de la console

        “It is seldom that liberty of any kind is lost all at once.” ― David Hume

        • [^] # Re: conflit avec WSL?

          Posté par  (site web personnel) . Évalué à 1 (+0/-0).

          merci, oui, c'est ça, avec les bonnes options on a accès aux gestions des extensions et l'accès de bash depuis les autres CLI (CMD, powershell).
          J'hésite pas à tout exporter notamment … env :) quitte à niquer find et sort.

  • # Shell powaa!!

    Posté par  (site web personnel) . Évalué à 2 (+0/-0).

    Le vrai langage de Shell portable, c'est PowerShell maintenant !

    Un syntaxe indigeste et lourde, mais qui permet de faire des trucs complexes qu'avant sous Windows et sous d'autres OS.

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.