1 points par GN⁺ 2024-07-30 | 1 commentaires | Partager sur WhatsApp
  • izabera/ps est une implémentation en Bash destinée à imiter, depuis Bash, une sortie proche de ps aux, même dans une situation où il est impossible de créer un nouveau processus
  • La condition clé est d’avoir un shell bash de confiance sur une machine accessible via ssh, mais de ne pas pouvoir créer de nouveaux processus parce que tous les autres PID sont utilisés
  • Le README présente cette situation comme un exemple de question d’entretien pour un poste nécessitant des connaissances en Bash/Linux
  • L’outil est décrit comme permettant de « faire plus ou moins comme si » l’on avait accès à un ps aux fonctionnel, sans garantir qu’il s’agit d’une réimplémentation complète
  • La phrase affirmant qu’il « fonctionne à 100 % sur toutes les machines et dans toutes les situations » est clairement une garantie humoristique

Quel est le projet

  • C’est un projet qui réécrit ps aux uniquement en Bash
  • Le titre du README est « ps aux written entirely in bash without ever forking »
  • Sa caractéristique principale est de ne jamais effectuer de fork pendant l’exécution

Situation envisagée

  • Le scénario d’exemple est le suivant
    • vous êtes connecté à une machine via ssh
    • vous êtes dans un shell bash familier
    • mais tous les autres PID sont utilisés, si bien qu’il est impossible de créer le moindre nouveau processus
  • Le README explique que, dans ces conditions, une fonctionnalité proche de ps aux peut être utile

Portée attendue et caveat

  • L’outil est présenté comme un moyen de « kinda sorta pretend » qu’un ps aux fonctionnel est disponible
  • La mention du README selon laquelle il « fonctionne parfaitement dans toutes les situations sur 100 % des machines, garanti » relève d’un humour exagéré
  • Le point central n’est donc pas une compatibilité complète, mais l’imitation de ps aux uniquement avec Bash dans un environnement extrême où il est impossible de créer de nouveaux processus

1 commentaires

 
GN⁺ 2024-07-30
Commentaires sur Hacker News
  • La blague selon laquelle le problème le plus difficile en informatique, c’était finalement aligner correctement les choses, me parle beaucoup
    J’ai écrit d’innombrables fonctions d’alignement de colonnes dans plusieurs langages, et c’était douloureux à chaque fois, alors que dans ma tête cela paraît simple, du genre « il suffit de calculer la longueur maximale de chaque colonne puis d’ajouter des espaces jusqu’au multiple suivant de la taille de tabulation »
    Même avec les f-strings de Python et les options de padding, le code devient vite complexe et difficile à lire, au point que j’ai corrigé plusieurs bugs rien qu’en réécrivant l’exemple pour ce commentaire, tellement c’est horrible

    • Il m’est même arrivé d’ajouter Pandas à un projet juste pour éviter d’écrire moi-même ce genre de code afin d’afficher un joli tableau
      Pour un usage aussi courant, on s’attendrait naturellement à ce qu’une bibliothèque existe, et honnêtement je suis surpris que cela ne fasse pas partie de la bibliothèque standard
    • https://perldoc.perl.org/perlform
    • J’ai déjà répondu sur Stack Overflow avec une solution en O(n) : https://stackoverflow.com/questions/10865483/print-results-i...
      L’idée est d’extraire la largeur et le nom des colonnes depuis description du curseur de base de données, de construire la ligne de séparation et la chaîne de formatage, puis d’afficher les lignes ; je ne sais pas s’il y a un bug fatal que j’aurais raté, mais cela ne me semble pas être un problème particulièrement difficile
    • Plus simplement, on peut aussi inverser les colonnes avec zip(*table) pour calculer la longueur maximale de chacune, puis afficher le tout avec f"{r:<{w}}"
      Le résultat ressemble alors à un tableau aux colonnes alignées, du type agony | kick | pump
    • À l’inverse, quand on doit souvent parser des données alignées en colonnes, ce n’est pas si simple non plus
      Il y a des espaces dans les valeurs, les champs sont remplis avec des espaces, parfois l’alignement est cassé et les colonnes débordent
      Il vaudrait peut-être mieux se mettre d’accord pour ne pas utiliser de données alignées en colonnes et adopter à la place un format plus simple, lisible par un humain, ce qui profiterait à tout le monde
  • Si j’étais connecté en SSH sur une machine où le shell Bash fonctionne encore mais où tous les PID sont épuisés et qu’il est impossible de créer un nouveau processus, j’irais fouiller le système de fichiers /proc/[pid]/ pour voir quel processus épuise l’espace de PID
    kill dans Bash est une commande interne au shell, donc elle n’a pas besoin de fork un nouveau processus comme /bin/kill
    Si on peut identifier le processus parent qui engendre les enfants responsables de l’épuisement des PID, on peut l’arrêter et reprendre le contrôle du système
    Ce script parse lui aussi /proc, et il est assez propre puisqu’il n’utilise ni pipes ni substitutions $(...) qui créeraient un nouveau sous-shell Bash

    • En entretien, il m’est arrivé de répondre « exec Python »
      Cela permet d’appeler les fonctions POSIX nécessaires sans exécuter de commande séparée, et la réponse avait été bien reçue
    • Honnêtement, moi je redémarrerais simplement
      Dans un environnement aussi limité, redémarrer puis restaurer le service peut être plus rapide que d’essayer de trouver et tuer le processus parent, et si les PID sont épuisés, il y a de fortes chances que d’autres choses soient déjà en mauvais état
    • Si l’on veut juste les PID et les noms de commande, on peut presque descendre à ceci : ps(){ (cd /proc;for i in [0-9]*;do echo $i: $(tr '\0' ' ' < $i/cmdline);done); }
    • L’idée d’aller voir dans /proc/[pid]/ quel processus épuise l’espace de PID est juste, mais d’après les commentaires du code source, l’auteur espérait au départ que /proc/*/status suffirait ; or des valeurs comme l’utilisation CPU n’y étaient pas disponibles
    • Concernant les sous-processus, je suis vraiment curieux de savoir comment fonctionnent [[ $cmdline ]] && exec {cmdline}>&- et exec {cmdline}< "$dir"/cmdline || continue
  • En 2011, j’ai passé un entretien pour un poste de SRE dans une assez grande entreprise technologique américaine, alors qu’à l’époque c’était même la première fois que j’entendais le terme SRE
    L’entreprise développait une alternative à MS Office dans le navigateur, et après un premier entretien téléphonique, il fallait programmer en direct avec l’intervieweur dans l’éditeur de documents de la société, tout en restant en appel
    Comme j’avais mis des notes élevées en shell scripting et en Linux dans ma grille d’autoévaluation, on m’a demandé de créer un remplaçant de netstat en Bash, mais à l’époque je ne savais pas où ni comment les informations de sockets étaient exposées dans /proc/, et j’ai vite compris que je n’y arriverais pas
    J’ai donc proposé à la place de faire une version miniature de ps et de fuser, et la solution que j’ai produite dans cet affreux traitement de texte basé sur le navigateur a été acceptée, ce qui m’a mené jusqu’aux entretiens sur site
    Avec le recul, je me demande si le scénario fictif qui motivait cet exercice n’était pas plus ancré dans la réalité qu’il n’y paraissait

    • Certains de ces utilitaires système vont probablement de toute façon inspecter procfs/sysfs en interne
      Moi aussi, je commencerais par là
  • J’avais créé pour m’amuser un site web interactif qui permet d’explorer ce genre de situation où, une fois connecté en SSH, on ne peut plus lancer de nouveau processus : https://oops.cmdchallenge.com

    • "echo *" n’affiche pas tous les fichiers du répertoire
      Il faut utiliser "echo .* *"
    • C’est sympa, mais après avoir terminé, on est renvoyé au premier niveau et on ne peut pas voir les autres, ce que j’ai trouvé frustrant
      J’aurais aimé consulter la liste "View Solutions" des autres niveaux pour voir quelles autres approches étaient possibles
  • Izabera est l’un des experts de #bash@libera
    J’ai énormément appris auprès de ces pointures depuis l’époque de freenode, au cours des dix dernières années

  • C’est du Bash assez propre
    D’expérience, le code Bash est souvent mal écrit et inefficace, mais celui-ci me semble être un bon contre-exemple

    • Du Bash propre devrait aussi être portable, or ce script est spécifique à Linux et se cassera sévèrement ailleurs
  • Que faire si l’on se retrouve dans un shell POSIX fiable, sans prise en charge de Bash ?
    Ce script Bash n’est pas compatible POSIX

  • Ce script ne fonctionne pas sous Bash 3.2, mais il marche sous Bash 4.2
    Sous Bash 3.2, on obtient l’erreur printf: '(': invalid format character, et l’environnement d’exemple est bash-3.2-33.el5_11.4.0.1

    • Ne pas prendre en charge une branche de Bash vieille de 18 ans et une branche de système d’exploitation vieille de 17 ans me paraît tout à fait raisonnable
  • Un meilleur usage serait sans doute de lister les processus sur un système où procps n’est pas installé
    C’est pas mal

  • On peut aussi faire des listeners et clients en Bash
    Je ne le recommande pas en production