Comment vérifier quel émulateur de terminal est actuellement utilisé?

15

J'ai gnome-terminal et Guake installés. Je veux donner différents messages de démarrage à afficher sur ces émulateurs de terminal au démarrage. Quel code dois-je écrire dans .bashrc pour que cela soit réalisé?

VedVals
la source

Réponses:

10

Cette fonction devrait faire le travail:

container() {
    pid=$$
    while true; do
        pid=$(ps -h -o ppid -p $pid 2>/dev/null)
        case $(ps -h -o comm -p $pid 2>/dev/null) in
        (gnome-terminal) echo "Running in gnome terminal";return;;
        (xterm) echo "Running in xterm";return;;
        (rxvt) echo "Running in rxvt";return;;
        (python) if [ ! -z "$(ps -h -o args -p $pid 2>/dev/null | grep guake)" ]; then echo "Running in Guake"; return; fi ;;
        esac
        [[ $(echo $pid) == 1 ]] && break
    done
}
container
jlliagre
la source
Bonne réponse! N'oubliez pas d'appeler réellement la fonction avec containeraprès la définition.
rosch
Je m'attendais à ce que cela soit évident, mais vous avez raison, la réponse a été mise à jour en conséquence.
jlliagre
@jlliagre J'ai essayé le code. Cela fonctionne bien sur gnome-terminal mais il a un problème sur Guake. Il ne donne aucune sortie. Au lieu de cela, il se bloque comme s'il était dans une impasse. Je dois Ctrl + C pour l'utiliser. Je n'ai pas vraiment compris le code, donc je ne sais pas où ça va mal.
VedVals du
Code fixe. J'ai manqué guake est géré par python et j'ai eu un bug empêchant la fonction de se fermer. Merci pour les commentaires.
jlliagre
Désolé mec, ça ne marche toujours pas. Donne une erreur bash: [: too many arguments. Got bash v4.2.24, python v2.7.3 si cela aide.
VedVals
10

Essaye ça:

echo $TERM

Cela fait plus autorité, mais pourrait être gâché par vos programmes. Cependant sur le mien, il dit xtermet sur ttys, il dit linux, ce qui, je pense, signifie Linux Console.

CMCDragonkai
la source
2
$TERMest une variable qui fait référence à la spécification telle que rapportée par l'émulateur de terminal que vous utilisez, et non à l'émulateur lui-même. Par exemple, sur mon système, echo $TERMrenvoie xtermmême si j'utilise en fait lxterminal. Ce qui se passe, c'est la conformité Xterm de lxterminal. lxterminal n'est pas réellement entièrement compatible avec xterm, vous devez donc faire attention. Les fichiers de spécifications se trouvent généralement dans /usr/share/terminfo.
stazher
7

Vous pouvez obtenir le nom de l'émulateur de terminal en saisissant le nom du processus parent. Par conséquent, cela fonctionne avec chaque émulateur de terminal.

En bash, zsh, etc.:

basename "/"$(ps -f -p $(cat /proc/$(echo $$)/stat | cut -d \  -f 4) | tail -1 | sed 's/^.* //')

Avec coquille de poisson:

basename "/"(ps -f -p (cat /proc/(echo %self)/stat | cut -d \  -f 4) | tail -1 | sed 's/^.* //')
mamiu
la source
Notez cependant que cela interceptera les arguments du programme lorsque l'émulateur de terminal sera lancé avec eux.
Robobenklein
Est-ce que cela fonctionne si je suis connecté via SSH?
user3731622
@ user3731622 ce ne sera pas! Vous devrez le transmettre depuis le client.
Enrico
2

Sur de nombreux echo $TERMretours de système Linux, xtermvoir le message Stazher ci-dessus.

Pour utiliser le terminal réel, procédez comme suit:

1: Fermez chaque instance de terminal en cours d'exécution.

2: Ouvrez un nouveau terminal en utilisant votre méthode habituelle.

3: Entrez la commande comme suit:

ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$)

4: Le retour devrait être quelque chose comme ça:

lxterminal --geometry=135x20

Voici la ventilation:

Donc: psest "l'état du processus"

L'option ps -oest Afficher les informations associées à la liste de mots clés spécifiée par des espaces ou des virgules. Cela semble compliqué, mais ce n'est pas vraiment le cas. (espace ou virgule) séparé (liste de mots-clés) spécifié.

Ainsi, (liste de mots clés) n'est 'cmd='qu'un seul mot clé dans la liste. Donc, il suffit de demander à afficher la commande pour ouvrir le terminal.

L'option ps -pest "by process id" Wow, c'est une très bonne option pour ps. Le problème est que vous devez transmettre à ps cet identifiant de processus. Alors, comment obtenir l'identifiant du processus? Nous déballons l'expression $(ps -o 'ppid=' -p $$)

Ici, nous devons commencer à réfléchir un peu plus profondément. J'aimerais avoir inventé ce bash one-liner, mais je ne l'ai pas fait. Je pense que je l'ai volé quelque part sur https://wiki.archlinux.org/ , je n'ai pas pu le retrouver. Ces gars-là sont géniaux, mais plusieurs fois je ne peux pas comprendre ce qu'ils disent de faire qu'après beaucoup d'études. Ce que nous pouvons faire, c'est le comprendre maintenant, car je vais vous l'expliquer.

nous savons donc $est opérateur d'expansion dans bash. J'aime penser "déballer". Donc, $(foo -opt bar)déroulera ou développera "foo -opt bar". Mais en bash, une seule accolade ronde (...)ouvre la sous-coque.

Ainsi, $(foo -opt bar)développe "foo -opt bar" comme exécuté dans le shell fille . Très bizarre et difficile à comprendre.

OK, maintenant nous exécutons à nouveau une commande presque identique, ps -o 'ppid=' -p $$mais cette fois ps, l'état du processus, nous montre ce qu'il peut voir à partir de l'instance de shell fille .

-oliste de mots clés, un seul mot clé comme avant, mais ppid=cela demande directement l'ID de processus du shell parent !! De DANS LA FILLE DE SHELL! Très intelligent, oui? Je suis tellement excité quand je peux comprendre ça!

-pencore une fois, "par l'ID de processus" et en bash $$est l'ID de processus.

Si vous appelez ps -o 'ppid=' -p $$, ou toute autre commande demandant $$directement à partir du premier shell, il pourrait dire pid = 1, ou le pid de xWindow, ou à partir de votre programme de bureau, ou vous obtiendrez peut-être un pid réel de shell. Si vous demandez plusieurs fois, vous obtiendrez peut-être une réponse différente à chaque fois!

Mais, si vous invoquez une fille et lui demandez "Who's your Daddy", elle vous le dira! Très intelligent. J'aimerais pouvoir être un tel génie pour inventer cette méthode.

stazher
la source
OK, donc AU ne permettra pas une ventilation appropriée dans un même article. Désolé, je ne veux pas me battre avec le système de blog et faire plusieurs articles. Vous pouvez peut-être vous faire une idée.
stazher
Votre autre réponse semble être un commentaire sophistiqué et informatif sur cette réponse plutôt qu'une réponse à la question ... Ce serait formidable si vous pouviez combiner vos deux réponses en une seule et en supprimer une, et y ajouter afin qu'elle répond pleinement à la question. Utilisez ---- pour tracer une ligne au milieu? Il y a aussi un bouton.
Zanna
Je pense avoir répondu à la question OP exactement et en détail. Vous avez sauté sur moi avant d'avoir eu la chance de comprendre le système d'édition de blog et de terminer. Faites descendre les votes, j'y suis habitué.
stazher
1
Je ne pense pas avoir sauté sur vous, je faisais juste une revue ... merci d'avoir rendu votre post plus complet
Zanna
Merci pour votre réponse. Je suis désolé, j'ai peut-être sauté sur toi. Je m'excuse beaucoup.
stazher
1

Utiliser pstreeet awkest le moyen le plus simple:

pstree -sA $$ | awk -F "---" '{ print $2 }'

Expliquant

  1. Affichez un arbre de processus avec pstreede $$(le processus atuel).
  2. Les pstreearguments:

    • -s: afficher les parents d'un processus
    • -A: affiche la sortie en ASCII pur.
  3. L' awkoutil analyse un modèle et un -Fargument est utilisé pour diviser les processus.

  4. Enfin, '{ print $2 }'indique de awkne sortir que le deuxième modèle de correspondance (dans ce cas, le nom de l'émulateur de terminal).
silvadev
la source
Êtes-vous sûr $2? Dans mon cas, ce qui est canalisé awkest en fait systemd---lightdm---lightdm---upstart---gnome-terminal----bash---pstree...
Enrico Maria De Angelis
@EnricoMariaDeAngelis Ya. Merci pour votre observation. Dans mon cas, l'émulateur de terminal s'initialise directement dans le service systemd. Je vérifie à nouveau le code et le modifie avec une correction.
silvadev
Cela ne fonctionne pas lorsque j'utilise un raccourci clavier pour lancer l'émulateur. Sur XFCE, j'obtiens à la xfsettingsdplace du terminal que j'utilise.
Michael Hoffmann
Fonctionne mieux si vous commencez par la fin:pstree -sA $$ | head -n1 | awk -F "---" '{ print $(NF-1) }'
lleaff
0

Vous avez raison, je n'ai fait que répondre à la question principale, pas à la question dans le corps. Alors voilà, et l'oncle de Bob.

Je ne sais pas de quoi parlait le changement de cas, dans une réponse ci-dessus. Un tel changement de boîtier n'est pas nécessaire. Mon script ~ / .bashrc n'est en fait qu'une simple ligne, toutes les commandes d'écho sont juste pour le plaisir. Comment expliquer...

Tout terme au démarrage lit ~ / .bashrc et exécute toutes les commandes qu'il verra dans .bashrc. Ainsi, quel que soit le terme appelé, il lira .bashrc et exécutera les commandes, donc seule la structure nécessaire dans .bashrc serait de modifier le comportement ou d'exclure un terme ou un autre. Le comportement souhaité est que chaque terme exécute la même commande, donc le commutateur de casse n'est pas nécessaire. Terminal lui-même vous dira comment il a été appelé, il n'est donc pas nécessaire de faire la différence.

Remarque (1) Je n'ai pas testé pour guake, mais fonctionne pour tous les autres mentionnés dans la première réponse par jlliagre.

Remarque (2) En raison du formatage dans le démarquage pour le wiki, vous ne pouvez pas couper et coller comme indiqué. Vous devez supprimer chaque backtick , y compris pour supprimer les caractères soulignés, et ajouter le backtick réel, sans espace avant psou après le -p $$).

script pour ~ / .bashrc

# show welcome message for actual terminal in use
echo "Welcome.  You are attempting to use"
echo ""
echo _backtick_ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$)_backtick_
echo ""
echo "Good Luck and God Speed."

C'était très amusant. J'ai ajouté ceci à mon propre ~ / .bashrc.

stazher
la source
par Note (1), ont testé sur Tilda, fonctionne très bien. Guake est similaire à Tilda, mais est écrit en python, donc je ne sais toujours pas à propos de Guake.
stazher
0

si vous utilisez bash, je pense que cette commande vous aidera:

which $(ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$))

Wang Shidong
la source
0

Si vous utilisiez ZSH, il existe une meilleure solution (plus rapide), qui n'utilise que les modules internes ZSH et manipule /proc/$pid/{stat,cmdline}directement.

get-terminal-emulator() {
    if [[ $TTY = "/dev/tty"* ]]; then
        echo "linux-console"
        return
    fi
    local pid=$$ name=''
    while true; do
        proc_stat=(${(@f)$(</proc/${pid}/stat)})
        name=${proc_stat[2]//[()]/}
        case "${name}" in
            gnome-terminal|konsole|rxvt|xterm)
                echo "${name}"; return ;;
            python*)
                local cmdline=(${(@f)$(</proc/${pid}/cmdline)})
                if [[ "$cmdline" =~ "\\bguake.main\\b" ]]; then
                    echo "guake"; return
                fi
                ;;
        esac
        if test "$pid" = "1" -o "$pid" = ""; then
            echo "unknown"
            return
        fi
        pid=${proc_stat[4]}       
    done
}
André von Kugland
la source