izabera/psest une implémentation en Bash destinée à imiter, depuis Bash, une sortie proche deps 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 auxfonctionnel, 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 auxuniquement en Bash - Le titre du README est «
ps auxwritten 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
- vous êtes connecté à une machine via
- Le README explique que, dans ces conditions, une fonctionnalité proche de
ps auxpeut être utile
Portée attendue et caveat
- L’outil est présenté comme un moyen de « kinda sorta pretend » qu’un
ps auxfonctionnel 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 auxuniquement avec Bash dans un environnement extrême où il est impossible de créer de nouveaux processus
1 commentaires
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
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
L’idée est d’extraire la largeur et le nom des colonnes depuis
descriptiondu 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 difficilezip(*table)pour calculer la longueur maximale de chacune, puis afficher le tout avecf"{r:<{w}}"Le résultat ressemble alors à un tableau aux colonnes alignées, du type
agony | kick | pumpIl 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 PIDkilldans Bash est une commande interne au shell, donc elle n’a pas besoin de fork un nouveau processus comme/bin/killSi 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 BashCela 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
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
ps(){ (cd /proc;for i in [0-9]*;do echo $i: $(tr '\0' ' ' < $i/cmdline);done); }/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/*/statussuffirait ; or des valeurs comme l’utilisation CPU n’y étaient pas disponibles[[ $cmdline ]] && exec {cmdline}>&-etexec {cmdline}< "$dir"/cmdline || continueEn 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 scriptinget enLinuxdans ma grille d’autoévaluation, on m’a demandé de créer un remplaçant denetstaten 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 pasJ’ai donc proposé à la place de faire une version miniature de
pset defuser, 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 siteAvec 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
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épertoireIl faut utiliser
"echo .* *"J’aurais aimé consulter la liste
"View Solutions"des autres niveaux pour voir quelles autres approches étaient possiblesIzabera 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
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 estbash-3.2-33.el5_11.4.0.1Un 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