2 points par GN⁺ 2024-06-24 | 2 commentaires | Partager sur WhatsApp
  • Quand les utilisateurs d’Unix placent des scripts personnels dans ~/bin/ et les ajoutent au PATH, des noms de commandes courts peuvent entrer en conflit avec de nouvelles commandes système
  • Dans des environnements comme Debian/Ubuntu, qui fournissent beaucoup de commandes, le risque augmente ; sur l’ordinateur portable Ubuntu cité en exemple, /usr/bin compte 21 733 commandes
  • Préfixer ses commandes personnelles par une virgule (,) permet au shell et aux outils de la traiter comme un caractère ordinaire de nom de fichier, tout en les distinguant facilement des commandes système
  • La virgule se saisit sans Shift et présente moins de risques de conflit que les parenthèses, l’antislash, les deux-points, l’accent grave, l’apostrophe, la barre oblique ou le point, qui ont une signification forte dans le shell
  • En appuyant sur Tab après ,, on peut parcourir directement la liste de ses commandes personnelles, ce qui facilite le maintien de noms propres pour les commandes de ~/bin/

Pourquoi les noms de commandes personnelles entrent en conflit

  • Beaucoup d’utilisateurs d’Unix créent un ~/bin/ dans leur répertoire personnel et l’ajoutent au PATH pour utiliser des commandes pratiques et des scripts shell personnels
  • Le problème est que les noms de scripts personnels sont généralement de courtes combinaisons de minuscules, qui ressemblent facilement aux commandes système par défaut
  • Lorsqu’une distribution Linux ajoute une nouvelle commande, son nom peut par hasard devenir identique à celui d’une commande personnelle existante
  • Dans les environnements de la famille Debian, le grand nombre de commandes fournies rend ce problème plus concret
    • Sur l’ordinateur portable Ubuntu cité en exemple, le décompte des commandes directement sous /usr/bin donne 21 733
    • apt-file search -x '^/usr/bin/[^/]*$' | wc -l

Les avantages du préfixe virgule

  • La solution consiste à renommer les commandes personnelles sous une forme facile à saisir, mais peu susceptible d’être choisie comme nom de commande système
  • Le critère de facilité de saisie est de ne pas utiliser la touche Shift ; il n’existe pas beaucoup de caractères sûrs qui satisfont cette condition
    • Les minuscules sont déjà fréquemment utilisées par les commandes système
    • Les parenthèses, l’antislash, les deux-points, l’accent grave et l’apostrophe ont une signification spéciale dans le shell
    • La barre oblique est le séparateur de répertoires et ne peut donc pas figurer dans un nom de fichier
    • Le point désigne un fichier caché en début de nom, et sert aussi souvent de séparateur d’extension à d’autres positions
  • L’option restante est la simple virgule (,) : les outils environnants et le shell la traitent comme un caractère ordinaire dans un nom de fichier
  • En ajoutant une virgule comme préfixe à chaque commande personnelle, on les distingue clairement des commandes système et l’on évite plus facilement les collisions de noms
  • Utilisée avec la complétion par Tab, elle permet de voir directement la liste des commandes personnelles après avoir saisi ,
    • La liste d’exemples comprend notamment ,complete-scp, ,complete-ssh, ,coreoff, ,coreon, ,find, ,go-thpgp, ,gr, ,hss, ,mount-thpgp, ,mount-twt, ,range, ,svn-store-password, ,umount
  • Cette méthode est utilisée depuis environ 10 ans et est recommandée comme façon de garder propres les noms de commandes personnelles dans ~/bin/

2 commentaires

 
GN⁺ 2024-06-24
Commentaires sur Hacker News
  • Au vu du seul titre, je pensais que ce serait une idée affreuse, mais en réalité ça me plaît plutôt bien. J’aime particulièrement la partie où l’on liste tous ses outils avec Tab
    Ces derniers temps, je ne rencontre pas souvent de conflits d’espace de noms, et c’est vrai qu’en étant passé au management, j’ai un peu perdu la main techniquement. J’ai l’impression que ma stack technique a dix ans de retard, et je me demande par où commencer pour me remettre à la page

    • La façon cool de faire aujourd’hui, c’est apparemment de construire soi-même quelque chose sur son temps libre et d’apprendre naturellement en le faisant. L’autosuffisance, la créativité et l’esprit d’initiative sont dans l’air du temps, et plus on construit, plus on est motivé à découvrir par soi-même des astuces pour résoudre de vrais problèmes et des approches modernes
    • Je suis aussi côté management, et j’ai l’impression que si je ne continue pas à suivre, mes compétences techniques vont se dégrader
      Ma méthode, c’est de créer moi-même des outils qui me simplifient la vie. Par exemple, si on a au travail un service web qu’on utilise souvent pour de simples consultations, je regarde s’il a une API et j’écris un CLI pour accélérer les tâches du quotidien. Une fois que c’est bien peaufiné à mon goût, je le partage avec l’équipe, mais convaincre les autres de l’essayer est difficile. Cela dit, comme je m’en sers tous les jours, je ne m’en préoccupe pas trop
    • Pour la même raison, j’ai fait un side project avec une autre stack plus à la mode, au lieu de celle que je connais au travail
      Le but était d’avoir une nouvelle perspective et de pouvoir parler des tendances, et une partie de tout ça est maintenant arrivée aussi dans mon travail. Du coup, j’ai aussi acquis une compréhension plus profonde des composants anciens
  • Je ne comprends pas bien le problème. Il suffit de mettre mon répertoire bin au début de $PATH plutôt qu’à la fin. Pour parcourir mes commandes, je lance simplement ls ~/bin

    • Et puis un jour, un outil s’attend à ce que $0 soit dans le chemin système, ça casse, et là commencent des heures de débogage frustrant
      Au final, c’est juste une question de choisir son poison
    • Il suffit de se souvenir du nom qu’on lui a donné, non ? Je ne vois pas pourquoi ça devrait ressembler à une sorte de hack
    • L’un des avantages, c’est qu’on peut utiliser l’autocomplétion fzf. Par exemple, dans fish, on peut taper la première lettre d’une commande puis appuyer sur Tab pour faire apparaître fzf
      Du coup, ,+Tab permet de filtrer rapidement les commandes personnalisées. À l’inverse, ls ~/bin demande beaucoup plus de frappe pour une opération fréquente, ou alors il faut peut-être commencer par retrouver l’autocomplétion avec ls+flèche vers le haut plusieurs fois
    • ls ~/bin est bien plus lent à taper que ,
  • Pour mes wrappers légers autour de git, j’utilise des noms de commandes personnalisés courts comme aa, st, di, dp, cm, le
    L’une d’entre elles entre effectivement en conflit avec un utilitaire installé par défaut sur certains systèmes. Malgré ça, comme mon répertoire bin passe avant les répertoires système dans $PATH, c’est ma commande qui gagne, et je n’ai pas grand intérêt pour l’outil en conflit. Si un autre outil utile pour moi entrait en conflit avec l’un des miens, je lui donnerais probablement un alias qui n’entre pas en conflit, plutôt que de renommer mon outil. Ces outils à deux lettres sont trop pratiques

    • Ce genre d’approche peut mener à des problèmes du type apt-get upgrade qui lance Dwarf Fortress
      https://askubuntu.com/questions/938606/dwarf-fortress-starti...
    • Oui. Les noms d’une à trois lettres devraient être réservés aux alias, fonctions et scripts utilisateur, ainsi qu’aux utilitaires standard
    • Mes alias git sont généralement des combinaisons de deux lettres commençant par g. Par exemple, gs, c’est git status
      Mais il m’arrive parfois d’avoir réellement besoin de GhostScript. C’est excellent, par exemple, pour intégrer des polices dans des fichiers PDF. En général, dans ce cas, j’utilise env gs
    • Toutes mes commandes personnelles commencent par j. Quand java est arrivé, c’est devenu assez amusant. Utiliser une virgule est une idée plutôt intéressante
      Heureusement que je n’avais pas choisi k, à cause de KDE :)
    • C’est peut-être un avis un peu tranché, mais je pense que les commandes système ne devraient pas être aussi facilement accessibles que les commandes utilisateur. Il devrait y avoir un espace de noms sous une forme ou une autre
      Par exemple, je pense que mkfs devrait s’appeler comme sys::mkfs. La frontière entre commandes système et commandes utilisateur peut se définir de plusieurs façons, et il y aura toujours des zones grises, mais si l’on peut exécuter par accident une commande dont on ignore même l’existence et qu’on n’a jamais explicitement installée, alors elle ne devrait pas être exposée directement dans l’espace de noms global.
  • Il y a une question connexe
    J’utilise surtout Windows et, comme l’auteur, j’ai créé plusieurs scripts CLI centrés sur Python que je place à l’équivalent de ~/bin/. Si on définit python.exe comme programme par défaut pour l’extension .py et qu’on ajoute .py à %pathext%, on peut taper simplement hello depuis n’importe quel chemin pour exécuter ~/bin/hello.py, et je m’en sers des centaines de fois par jour. J’utilise davantage Linux ces jours-ci, mais je suis encore débutant et je n’ai pas réussi à mettre en place la même chose. On dirait que Linux n’a pas de notion de « programme associé », donc on ne peut pas simplement appeler un fichier .py et laisser le shell l’exécuter avec Python. Bien sûr, on peut faire un chmod +x sur le script, mais il faut alors y mettre un shebang, ce qui me gêne parce que ça ressemble à du hardcoding. Je me dis que si plus tard je veux exécuter mes scripts .py avec /usr/bin/nohtyp au lieu de /usr/bin/python, ça posera problème. Et je n’ai pas non plus trouvé comment omettre la partie .py à l’appel du script. Ce n’est pas une critique de la conception de Linux, je sais qu’il a beaucoup d’avantages, mais j’aimerais vraiment pouvoir exécuter hello.py présent dans le $PATH en tapant hello

    • Sous Linux, je pense toujours que le shebang est l’outil adapté à ce problème. Si on veut faire simple, on peut mettre un lien symbolique my_python dans un répertoire du chemin, puis utiliser /usr/bin/env my_python dans le shebang
      Si tu veux une approche plus propre, regarde l’outil update-alternatives. Il fournit ce type d’abstraction de manière plus générale : https://linuxconfig.org/how-to-set-default-programs-using-up...
    • D’autres ont déjà donné la solution, mais je voudrais ajouter une explication sur le pourquoi
      Sous Linux — et en fait sur la plupart des plateformes hors Windows — la signification des extensions de fichier est bien plus faible. La possibilité d’exécuter n’importe quel type de fichier dépend non pas de son extension, mais de choses comme le drapeau +x. Cela permet de réécrire une commande dans un autre langage d’implémentation sans casser les appels qui la visent. L’extension .py n’a de sens que pour les modules importés ; pour un script exécutable, il suffit de regarder le shebang quand c’est nécessaire. Les scripts distribués à l’extérieur utilisent en général #!/usr/bin/env python, tandis que ceux inclus dans des paquets de distribution sont souvent réécrits en #!/usr/bin/python ou équivalent. Le shebang ne prend pas en charge plusieurs arguments, mais GNU env propose l’option -S pour imiter ce comportement. Cela dit, le problème de longueur des arguments demeure
    • Il suffit d’enlever .py du nom du fichier. L’appeler "hello" est tout à fait acceptable
      Je vois mal quels seraient les inconvénients du shebang. Si tu veux vraiment l’exécuter avec un autre interpréteur, il suffit de le préciser, par exemple "nohtyp hello". Et si ça te dérange vraiment, tu peux définir un alias dans ton fichier d’initialisation du shell. Avec bash, par exemple : alias hello="python3 /path/to/hello.py". Si tu en as envie, tu peux même écrire un petit script qui crée automatiquement ce genre d’alias pour le contenu d’un répertoire donné
    • Cette notion existe, mais pas dans la syntaxe du shell. C’est en général une question au niveau de l’application, déléguée à l’environnement de bureau/GUI
      Dans les scripts shell, on ajoute généralement un shebang et on rend le fichier exécutable, de sorte que l’exécutable soit déclaré dans le script lui-même. On peut considérer le shebang comme une sorte d’extension de fichier. Si chmod +x ./malware.py puis ./malware.py ne fonctionnent pas, il faut vérifier le chemin indiqué par le shebang. Si l’interpréteur peut exécuter le script comme un argument ordinaire, on peut aussi obtenir un comportement similaire avec quelque chose comme xdg-open malware.py. Ce serait l’équivalent d’un double-clic dans le gestionnaire de fichiers par défaut. Quand j’utilisais Linux comme système principal de bureau, j’avais un alias xop, mais je ne l’utilisais que pour les fichiers de données comme les images ou les documents, pour lesquels le comportement par défaut était déjà le bon. Je ne recommande pas de définir l’interpréteur comme programme par défaut pour les scripts exécutables. Par défaut, on peut aussi vouloir ouvrir un script dans un éditeur plutôt que l’exécuter. Je pense que xdg-open est plutôt un outil côté Gnome, mais ça ne veut pas dire qu’il est inutilisable ailleurs ; je l’ai aussi utilisé sous Xubuntu. Si tu veux vraiment que tous les fichiers Python s’exécutent par défaut aussi en contexte GUI, il doit être possible de configurer ce comportement, et man xdg-open peut aider. Encore une fois, ce n’est pas un bon conseil
    • Cela ne répond pas directement à ton objectif, mais le shebang n’est qu’à moitié du hardcoding. La « bonne » façon d’utiliser un shebang, malgré quelques réserves mentionnées ici : https://unix.stackexchange.com/a/29620, c’est #!/usr/bin/env python
      Ainsi, c’est le python trouvé en premier dans le chemin qui sera exécuté. Si plus tard tu veux utiliser /usr/bin/nohtyp au lieu de /usr/bin/python, tu peux créer un lien symbolique python pointant vers /usr/bin/nohtyp dans un répertoire recherché avant /usr/bin. Par exemple, il suffit d’ajouter ~/myCommandPreferences au début du $PATH
  • Une autre manière d’éviter les conflits dans le $PATH consiste à donner au binaire un nom très long, peu susceptible d’être utilisé par d’autres exécutables, puis à définir un alias court dans bashrc
    Les alias n’affectent pas les exécutables appelés à l’intérieur des scripts, et dans mes scripts je peux continuer à faire référence au nom long. L’inconvénient, c’est qu’on n’obtient pas le même niveau d’ergonomie avec l’autocomplétion par tabulation, même si cet aspect est vraiment agréable. Il peut aussi rester des conflits pour des scripts qui, comme le script d’activation de venv en Python, doivent être source plutôt qu’exécutés comme sous-processus, mais ce cas reste rare

    • Avec zsh, on a aussi cette autocomplétion
  • Le fait de commencer par une virgule est aussi une technique courante dans la communauté des text expanders / remplacements de texte

    • Oui. La plupart de mes alias vim commencent aussi par ,
  • J’ai récemment regardé dans ~/.local/bin/ et j’y ai trouvé des dizaines d’exécutables que je ne me souvenais pas avoir mis là
    La plupart étaient liés à pyside, mais il y avait aussi d’autres scripts. J’ai dû les ouvrir un par un pour me rappeler lesquels j’avais écrits moi-même et lesquels venaient d’ailleurs. Si mes scripts avaient commencé par une virgule, ça aurait été beaucoup plus rapide, et ça m’aurait aussi aidé à me souvenir de la raison de leur création avant même de les ouvrir

    • En général, ~/.local/bin/ sert aux scripts installés, tandis que ce qu’on écrit soi-même en local va dans ~/bin/
  • Je passe mon tour. Il suffit de mettre le bin personnel avant $PATH, et d’utiliser /usr/bin ou /bin quand on veut référencer un programme masqué
    On peut lister les outils personnalisés avec ~/bin/[Tab]

    • Je ne comprends pas l’idée de devoir continuer à se souvenir de la virgule alors qu’on ne veut pas forcément masquer ses propres utilitaires système tout en gardant le même nom
      Si je n’aime pas le grep du système, par exemple le grep de Solaris, et que je préfère le grep de GNU, pourquoi ne pas simplement le laisser sous le nom grep ?
  • Le fait d’avoir découvert cette idée il y a cinq ans m’a permis de mettre de l’ordre dans mon recueil d’astuces shell. En combinant des alias et ~/bin, j’ai maintenant plus de 50 commandes virgule, et ma vie dans le shell est bien plus fluide qu’avant, quand tout était mélangé

  • Cela a aussi été discuté en 2020 : https://news.ycombinator.com/item?id=22778988 (90 commentaires)

 
kayws426 2024-06-24

Que pensez-vous d’utiliser « _ » ?