Comment détecter le nombre de terminaux ouverts par l'utilisateur

9

J'utilise Ubuntu et je peux changer manuellement la bashcouleur de l'invite du shell en vert en utilisant

export PS1="\e[0;32m[\u@\h \W]\$ \e[m" 

Cependant, je veux que la couleur de l'invite du shell change automatiquement chaque fois que j'ouvre un nouveau terminal ou un nouvel onglet. Je sais que le terminal tty de base a 16 couleurs, et il est correct de faire pivoter les couleurs si plus de 16 terminaux sont ouverts. La solution fonctionnera-t-elle également lorsque je me connecte via Putty, tmuxou screen.

Mon idée est d'écrire un script shell et de le placer dans .bashrclequel détecte la nouvelle session de terminal que l'utilisateur a ouverte et incrémente un compteur global de \e[0;31m[à \e[0;47m[. Comment détecter le nombre de terminaux ouverts par l'utilisateur?

manav mn
la source

Réponses:

8

Si vous avez vraiment besoin d'obtenir le nombre de terminaux que vous avez ouverts, optez pour le comptage des fichiers qui vous appartiennent /dev/pts(bien que cela puisse inclure ceux ouverts par des processus d'arrière-plan, pas par des émulateurs de terminaux graphiques). Sinon, comptez le nombre de processus enfants de vos émulateurs de terminaux, comme indiqué par Jacob dans la première ligne de sa réponse.

Évitez de vous fier à whola sortie de et de rechercher des gnome-pty-helperprocessus, car ceux-ci ne fonctionnent pas dans les gnome-terminalversions plus récentes.

Notez que de nos jours, presque tous les émulateurs de terminaux graphiques (y compris le mastic) et les multiplexeurs (écran, tmux) prennent en charge 256 couleurs. Vous pouvez obtenir de très belles invites colorées si vous utilisez cette palette.

Ma recommandation pour une solution très simple est de baser la couleur sur le numéro de la ligne tty actuelle. Par exemple, traitez la sortie de la ttycommande pour ne prendre que le nombre et en dériver la couleur. Un certain numéro de ligne tty n'est donné qu'à un terminal à la fois, vous devez d'abord fermer ce terminal avant que le même numéro de ligne ne soit réémis par le noyau. Ceci, combiné avec 256 couleurs, garantit automatiquement que vous ne verrez pas la même couleur deux fois à un moment donné (et même avec 16 couleurs, cela donnerait une distribution assez uniforme). Pas besoin de maintenir un compteur global, et pas besoin de compter des terminaux ou des processus.

egmont
la source
1
Belle idée avec tty. Je suppose que nous / les autres nous sommes trop concentrés sur cette "question" et avons oublié qu'il pourrait y avoir d'autres solutions pour le "besoin" entier :) Je jouerais même avec l'implémentation d'un sélecteur de couleur aléatoire. S'il s'agit de 256 couleurs, la sélection de couleurs identiques / similaires ne devrait pas se produire beaucoup. Cependant, le réglage manuel des couleurs pour des nombres de points donnés donnera une meilleure personnalisation.
GreggD
@TedM. Oui, la question était à peu près formulée comme une question XY, dans le sens de: "Je souhaite avoir une couleur différente dans chaque terminal, alors dites-moi: comment puis-je compter le nombre de terminaux?"
egmont
@TedM. Le hasard est aussi une bonne idée! (Une propriété d'un mappage déterministe est qu'après le sudoing, le nouvel utilisateur peut facilement définir la même couleur d'invite. Cela peut ou non ce que le demandeur d'origine veut avoir.)
egmont
1
Randomizer est assez facile: color="\e[38;5;"$(((RANDOM % 231 )+1))"m"(seulement 231 pour rejeter les niveaux de gris), cependant beaucoup de ces couleurs se sont avérées être simplement des nuances différentes et quelques-unes sont sombres, donc elles pourraient être presque invisibles et je pense que personne ne les utilisera dans la vraie vie ...
GreggD
Nous ne connaissons pas la version Ubuntu du demandeur. En 16.04, il n'y a définitivement plus de gnome-pty-helper ( git.gnome.org/browse/vte/commit/?id=299c700 ). Je ne vais pas rétrograder pour vérifier la hiérarchie exacte des processus dans les anciennes versions. Je sais qu'il y avait autrefois un tel processus, je ne suis tout simplement pas tout à fait sûr à quoi ressemblait la hiérarchie parent-enfant. Soit dit en passant, j'ai pris l'idée du nombre de processus enfants de votre réponse d'origine, donc je ne comprends pas cela "(également par vous)", peu importe.
egmont
5

Dans une situation d'utilisateur unique, si nous prenons l'exemple de xterm, nous pouvons simplement compter le nombre de pids de xterm; xtermcrée un pid distinct pour chaque fenêtre.
gnome-terminalexécute cependant un seul pid, mais la bonne nouvelle est qu'il crée un processus enfant pour chaque fenêtre et / ou onglet. nous pouvons récupérer ces processus enfants par la commande:

pgrep -P <pid_of_gnome-terminal>

Il y a cependant quelques complications à gérer:

  • En lisant votre question, nous pouvons supposer que l' utilisateur dans ce cas est en fait le propriétaire de la x-session . Habituellement, nous pouvons simplement utiliser la $USERvariable -variable, mais cela peut ne pas correspondre à l'utilisateur actuellement connecté de $DISPLAY.

  • Dans une situation multi-utilisateurs, les pids appartenant à l'application terminale (ou laquelle) n'appartiennent pas nécessairement au courant $DISPLAY. Nous devons séparer uniquement les pids et les pids enfants pertinents.

  • Sous Unity (15.10 ou inférieur), si un deuxième utilisateur se connecte, un processus supplémentaire est démarré ( gnome-pty-helper), qui apparaît comme un processus enfant dans gnome-terminal, mais le processus (évidemment) n'a ni fenêtre ni onglet. Sur Mate , le processus existe quand même.

En bref

Pour compter le nombre d'onglets et / ou de fenêtres d'une application de terminal, nous devons:

  • Voyez si nous exécutons une application de terminal qui a plusieurs pids ou un seul pid sur un $DISPLAY(x-session)
  • À partir des processus en cours, séparez uniquement les pids pertinents, en cours d'exécution sur ce$DISPLAY
  • Si l'application exécute des processus enfants pour son pid (pour les fenêtres / onglets), voyez si elle gnome-pty-helpers'exécute, pour corriger le nombre.

Cependant, cela peut très bien être scripté, pour trouver de manière fiable le nombre de fenêtres et / ou d'onglets actuellement ouverts.

Le scénario

Dans le script ci-dessous, l'application de terminal ciblée est utilisée comme argument . Le script fonctionne sur de nombreux terminaux sur lesquels je l'ai testé. Une exception est Tildaen ce moment.

Un exemple

  • J'ai deux utilisateurs connectés, un (pas l'actuel) avec deux gnome-terminalfenêtres, un (celui de l'image) avec trois gnome-terminalfenêtres et deux xtermfenêtres.

entrez la description de l'image ici

La commande:

/path/to/get_terms.sh gnome-terminal

les sorties:

3

tandis que

/path/to/get_terms.sh xterm

les sorties:

2

Le scénario

#!/bin/bash

terminal=$1

# get the user running the current x-session
username=$(who | grep $DISPLAY | head -1 | awk '{print $1}')
# get the pid of the terminal for the current user
userpid=$(pgrep -u $username $terminal)
# check what type the terminal is (multi pid/single pid)
npids="$(echo "$userpid" | wc -w)"
# in case of a single pid, count the children
if [ "$npids" -eq 1 ]; then
  # check if gnome-pty-helper runs (starts when multiple users are logged in)
  ptpid=$(pgrep gnome-pty-helpe)
  # get number of child- procs
  let "orig = $( pgrep -P $(pgrep -u $username $terminal) | wc -w )" 
  # if pty-helper runs, correct the number of child procs
  if [ -n "$ptpid" ] && [ -n "$userpid" ]; then
    let "n_terms = $orig-1"; else let "n_terms = $orig"
  fi
  # if no child procs run, n-terminals = n-counted pids (difference Mate <> Unity)
  if [ "$n_terms" -eq 0 ]; then echo $orig; else echo $n_terms; fi
# in case of multiple pids, count the pids
elif [ "$npids" -gt 1 ]; then echo $npids
fi

Utiliser

  • Copiez le script dans un fichier vide, enregistrez-le sous get_terms.sh, rendez-le exécutable et exécutez-le par la commande:

    /path/to/get_terms.sh <terminal_application>
Jacob Vlijm
la source
Ici, j'en ai toujours un en gnome-pty-helpercours d'exécution, même lorsqu'il n'y a qu'un seul utilisateur connecté (juste après le redémarrage) et lorsque j'ouvre une quantité de terminaux, il fonctionne en deuxième, même aide. Votre nouveau script semble fonctionner pour mate-terminal (n'a pas pu provoquer ce zéro-chose), mais avec xterm, quand je n'ai qu'un seul ouvert, il montre 0et commence à afficher un bon nombre seulement après le deuxième et avec gnome-terminal il en montre toujours un de moins (sortie 0quand un seul est ouvert).
GreggD
@TedM. Merci, ce sont des informations utiles, corrigées maintenant.
Jacob Vlijm
J'admire vraiment votre "passion" :) ... mais il y a toujours un problème avec gnome-terminal. Un donne 1, deux donne 1, trois donne 2, quatre donne 3, etc. Plus ma nouvelle découverte, le "Tilda" de MATE (ce terminal supplémentaire "inconnu" dans ma réponse) a également le même problème que gnome-terminal, mais avec ses onglets. Cependant, xterm et mate-terminal semblent bien fonctionner.
GreggD
@TedM. Merci d'avoir mentionné! Question idiote, mais êtes-vous sûr d'utiliser le dernier code? Sur Mate 15.10 tous les tests, je lance le travail sans exception. Quelle est votre version Mate? Sur Unity, tout fonctionnait déjà bien.
Jacob Vlijm
@TedM. Aussi sur mon joli 15.10 Mate vierge, il est là par défaut. Il suffit de refaire les tests, parfaitement! puis-je vous demander demain ou alors d'exécuter une version modifiée du script et de publier la sortie quelque part, pour voir ce qui cause l'exception dans votre cas?
Jacob Vlijm
1

Une awkfaçon:

who | awk 'BEGIN{count=0}{ if(NR!=1){count++} }END{print count}'

Explication:

Dans la commande ci-dessus 1, awkest utilisée pour trouver le nombre de terminaux. Dans le awkprogramme, il vérifie simplement le nombre de lignes renvoyées par la commande who - 1.

fouiner
la source
cela renvoie 0 pour moi, ce qui est clairement faux ...
Zanna
Celui-ci fonctionne très bien pour mon terminal et mon terminal, semble à l'épreuve des balles.
GreggD
En bref:, who | awk 'END{print NR - 1}'puisque ce que vous voulez, c'est le nombre de lignes - 1.
muru
0

Un moyen simple peut également être juste de s'exécuter System Monitor(si vous démarrez à partir du terminal, vous devez écrire gnome-system-monitor) et sous l'onglet "Processus", organisez les processus en cours par nom et comptez le nombre d'occurrences de Bashdans la liste (ils seront tous ensemble si vous organisez par nom, il est donc facile de compter).

Notez que vous devez rechercher Bashet non Gnome Terminalsi vous voulez voir le nombre de terminaux ouverts par utilisateur. Une fois que vous ouvrez un terminal, Gnome Terminalil apparaîtra également dans la liste des processus, mais n'en restera qu'un même si plusieurs terminaux sont ouverts. Le bouton "Afficher" System Monitorvous permet de définir les processus à afficher, par exemple. Tous les processus / processus utilisateur / actif ...

NonStandardModel
la source
Étant donné que OP souhaite utiliser le résultat pour définir automatiquement la ou les couleurs du terminal, cela ne semble pas être une option vraiment pertinente.
Jacob Vlijm
Désolé, je vois maintenant qu'il veut l'utiliser dans le script. Mais alors serait ps -ef | grep UserName | grep bash | grep -v grep | wc -l ne fonctionne pas?
NonStandardModel