Comment puis-je obtenir le nom du terminal actuel à partir de la ligne de commande?

25

Est-il possible d'obtenir le type de terminal avec une commande?

Si j'utilise gnome-terminal, la sortie devrait être gnome-terminalou quelque chose de similaire. Il serait également intéressant d'obtenir la version du terminal.

Mise à jour

ps -aux | grep `ps -p $$ -o ppid=` 

produira quelque chose comme ceci:

user     4239  0.0  0.7 292708 15744 pts/8    Sl   11:39   0:02 xfce4-terminal
user     4800  0.0  0.0   6176   820 pts/0    S+   12:23   0:00 grep --color=auto  4239

Cela fonctionnera également avec xterm, mais comment obtenir uniquement le nom ( xfce4-terminaldans ce cas)?

TuKsn
la source
Je viens de mettre à jour ma réponse avec une approche différente et meilleure. Si vous avez le temps, jetez un œil et faites-moi savoir si cela fonctionne aussi pour vous.
terdon
Merci mais premier problème avec rxvt -> window 31457282 has no pid associated with it(testé sur Lubuntu)
TuKsn
Oh? Merde, c'est bizarre. J'ai testé sous Cinnamon.
terdon

Réponses:

29

Version originale

Pour ce faire, vous pouvez obtenir le processus parent de votre session shell actuelle et à partir de là le nom du terminal.

  1. Récupère le parent du processus shell actuel. La variable bash $$est le PID de votre shell actuel, nous pouvons donc donner cela en tant que requête à ps( -p $$) et lui demander d'imprimer le PID du processus parent ( -o ppid=, la fin =est d'éviter d'imprimer les en-têtes de colonne):

    $ ps -p $$ -o ppid=
    544
    

    Ainsi, le PID du parent de mon shell est 544.

  2. Obtenez le processus associé à ce PID et imprimez sa ligne de commande

    $ ps -p 544 o args=
    /usr/bin/python /usr/bin/terminator
    

    La sortie ci-dessus dépendra de l'émulateur de terminal que vous utilisez, j'utilise terminator.

  3. Combinez tout en une seule commande

    ps -p $(ps -p $$ -o ppid=) o args=
    
  4. Utilisez-le pour obtenir la version

    $(ps -p $(ps -p $$ -o ppid=) o args=) --version
    terminator 0.97
    
  5. Ajoutez une petite fonction à votre ~/.bashrcqui retourne le nom et la version de l'émulateur de terminal que vous utilisez (cela fonctionne pour les émulateurs de terminal les plus courants):

    which_term(){
        term=$(ps -p $(ps -p $$ -o ppid=) -o args=);
        found=0;
        case $term in
            *gnome-terminal*)
                found=1
                echo "gnome-terminal " $(dpkg -l gnome-terminal | awk '/^ii/{print $3}')
                ;;
            *lxterminal*)
                found=1
                echo "lxterminal " $(dpkg -l lxterminal | awk '/^ii/{print $3}')
                ;;
            rxvt*)
                found=1
                echo "rxvt " $(dpkg -l rxvt | awk '/^ii/{print $3}')
                ;;
            ## Try and guess for any others
            *)
                for v in '-version' '--version' '-V' '-v'
                do
                    $term "$v" &>/dev/null && eval $term $v && found=1 && break
                done
                ;;
        esac
        ## If none of the version arguments worked, try and get the 
        ## package version
        [ $found -eq 0 ] && echo "$term " $(dpkg -l $term | awk '/^ii/{print $3}')    
    }

    Vous pouvez maintenant obtenir le nom du terminal et lui transmettre également toutes les options que vous souhaitez (telles que --version.

Quelques exemples utilisant différents terminaux:

  1. xterm

    $ which_term
    XTerm(297)
    
  2. terminator

    $ which_term 
    terminator 0.97
    
  3. rxvt, celui-ci n'a aucun des drapeaux ou -V, donc aucune information de version n'est imprimée.-version--version

    $  which_term
    rxvt  1:2.7.10-5
    
  4. gnome-terminal.

    $ which_term
    gnome-terminal  3.10.1-1
    
  5. konsole

    $ which_term
    Qt: 4.8.6
    KDE Development Platform: 4.11.3
    Konsole: 2.11.3
    
  6. lxterminal

    $ which_term
    lxterminal  0.1.11-4
    
  7. xfce4-terminal

    $ which_term
    xfce4-terminal 0.6.2 (Xfce 4.10)
    
    Copyright (c) 2003-2012
        The Xfce development team. All rights reserved.
    
    Written by Benedikt Meurer <[email protected]>
    and Nick Schermer <[email protected]>.
    
    Please report bugs to <http://bugzilla.xfce.org/>.
    

Nouveau et amélioré

L'approche ci-dessus n'est cependant pas digne de confiance. Il s'étouffera lorsque vous exécutez votre shell après avoir suconsulté un autre utilisateur ou lorsque votre terminal est associé à quelque chose et à divers autres cas. Comme nous travaillons évidemment avec des programmes X ici, une meilleure façon pourrait être d'utiliser quelque chose comme xdotool(installable avec sudo apt-get install xdotool) pour obtenir les informations à la place:

perl -lpe 's/\0/ /g' /proc/$(xdotool getwindowpid $(xdotool getactivewindow))/cmdline

Ce qui précède imprimera la ligne de commande utilisée pour lancer la fenêtre actuellement active. Étant donné que votre terminal sera probablement actif, c'est la commande qu'il affichera. Cela signifie que pour la plupart des émulateurs de terminaux, vous pouvez supposer en toute sécurité que le 1er champ renvoyé est le nom du terminal:

$ which_term 
lxterminal 

Cela signifie que l'obtention de la version est triviale. Par exemple

$ dpkg -l $(which_term) | awk '/^ii/{print $3}'
0.1.11-4

Ce n'est pas le cas pour gnome-terminal:

$ which_term 
/usr/lib/gnome-terminal/gnome-terminal-server 

ou terminator:

$ which_term
/usr/bin/python /usr/bin/terminator 

Donc, nous pouvons le rendre un peu plus complexe (il y a des bashismes ici, celui-ci n'est pas portable):

which_term(){
    term=$(perl -lpe 's/\0/ /g' \
           /proc/$(xdotool getwindowpid $(xdotool getactivewindow))/cmdline)

    ## Enable extended globbing patterns
    shopt -s extglob
    case $term in
        ## If this terminal is a python or perl program,
        ## then the emulator's name is likely the second 
        ## part of it
        */python*|*/perl*    )
         term=$(basename "$(readlink -f $(echo "$term" | cut -d ' ' -f 2))")
         version=$(dpkg -l "$term" | awk '/^ii/{print $3}')
         ;;
        ## The special case of gnome-terminal
        *gnome-terminal-server* )
          term="gnome-terminal"
        ;;
        ## For other cases, just take the 1st
        ## field of $term
        * )
          term=${term/% */}
        ;;
     esac
     version=$(dpkg -l "$term" | awk '/^ii/{print $3}')
     echo "$term  $version"
}

Cela fonctionne pour tous les cas sur lesquels j'ai testé.

terdon
la source
@ Xubu-Tur hmm, j'ai seulement essayé en lançant manuellement chaque terminal depuis un autre terminal et cela a bien fonctionné. Je suppose que les menus de votre environnement de bureau ont un chemin différent ou diffèrent en quelque sorte dans la façon dont ils lancent les terminaux. Je pourrais peut-être vous donner quelque chose de mieux si vous me dites exactement comment vous les avez lancés et quelle erreur vous avez eue. Si vous avez lancé à partir d'un menu, vérifiez la commande exécutée par l'élément de menu.
terdon
@ Xubu-Tur n'ajoute pas de capture d'écran. Collez simplement le message d'erreur dans votre question. Même chose pour la commande que l'élément de menu lance. Ne vous attendez pas à ce que je le copie manuellement à partir d'une image!
terdon
2
Vous pouvez simplement utiliser $PPIDpour obtenir le PID du processus parent.
nyuszika7h
@ nyuszika7h oui vous pouvez et +1 pour cela mais je préfère ne pas. Je viens de vérifier et ce n'est pas disponible en kshou tcsh. C'est une très bonne idée pour la famille bash car c'est beaucoup plus simple que mon approche.
terdon
Il est certainement disponible en ksh93et en mksh.
nyuszika7h
8

Essaye ça,

ps -aux | grep `ps -p $$ -o ppid=` | awk 'NR==1{print $11}'

OU

ps -aux | grep `ps -p $$ -o ppid=` | awk 'NR==1{print $NF}'
Avinash Raj
la source
Le premier échoue sur rxvtet terminatoret la seconde échoue sur uxtermet gnome-terminal(il imprime /usr/lib/gnome-terminal/gnome-terminal-server). Ils échoueront tous (comme le mien) si vous utilisez une session su.
terdon
7
basename "$(cat "/proc/$PPID/comm")"

$PPIDest le PID du processus parent du shell. commsignifie commande . Il peut ou non s'agir d'un chemin complet, nous utilisons donc basenamepour supprimer le chemin si nécessaire.

Avertissements

Celles-ci s'appliquent probablement à au moins certaines des autres réponses également.

  • commest techniquement argv[0], qui peut en fait être une chaîne arbitraire. Mais en général, vous devriez pouvoir vous y fier pour ce cas particulier.

  • Cela ne fonctionnera pas comme prévu si vous vous connectez via SSH ou utilisez tmux, screenou quelque chose de similaire.

nyuszika7h
la source
C'est très agréable +1, mais sur le terminal de terminaison, je ne reçois qu'en terminsortie.
TuKsn
Je ne sais pas pourquoi, c'est probablement la faute de Terminator.
nyuszika7h
C'est parce qu'il est exécuté comme un script python, je pense. C'est vraiment agaçant.
terdon
Veuillez noter que ce $PPIDn'est pas standard dans tous les réservoirs. par exemple dans tcshJe reçois:PPID: Undefined variable.
arielf
2

Vous pouvez essayer la commande suivante:

$ dpkg-query -W $COLORTERM
gnome-terminal  3.6.2-0ubuntu1

Mise à jour (grâce à OP et Avinash Raj):

$ dpkg-query -W $(ps -aux | grep "`ps -p $$ -o ppid=`" | awk 'NR==1{print $11}' | xargs basename)
rxvt    1:2.7.10-5
Sylvain Pineau
la source
Je pense qu'il veut le savoir pour la session terminale active :) Donc s'il utilise "putty" à ce moment-là ...
Rinzwind
Non pas plus de "mastic" mais qu'en est-il de xterm, avec cette commande j'obtiens aussi gnome-terminal 3.6.2-0ubuntu1ldans xterm?
TuKsn
2
Cela n'imprime pas le terminal que vous utilisez actuellement. Il imprime tout ce qui a été défini comme $ COLORTERM par défaut, cela n'a rien à voir avec ce que vous utilisez à l'époque.
terdon
La mise à jour fonctionne bien également avec xterm et affiche la version et le nom.
TuKsn
Tout le mérite revient à @Avinash et à vous pour la bonne commande. Je viens d'ajouter la version.
Sylvain Pineau
2

Une autre possibilité (pas parfaite) est:

xprop -id $WINDOWID WM_CLASS | cut -d" " -f3 | sed 's/^.\(.*\)..$/\1/'

Mais cela ne fonctionne pas avec lxterminal car la variable d'environnement est $WINDOWIDvide ...

Terminator affiche le nom "x-terminal-emulator".

TuKsn
la source
0

Le terminal actuel peut également être détecté via une séquence d'échappement: les attributs du périphérique (DA secondaire)

Par exemple en bash:

read -s -dc -p $'\E[>c' da;da=${da##$'\E'[>};echo "${da//;/ }"

Cela ne renvoie qu'une sorte d'identifiant - et malheureusement je ne connais pas de liste officielle qui les traduise en noms réels.


Pour une implémentation réelle, qui traduit certains identifiants connus en noms de terminaux, consultez cet exemple de script bash: https://github.com/mintty/utils/blob/master/terminal

TS
la source