Wie kann ich überprüfen, welcher Terminalemulator gerade verwendet wird?


15

Ich habe Gnome-Terminal und Guake installiert. Ich möchte verschiedene Startmeldungen geben, die auf diesen Terminalemulatoren beim Start angezeigt werden. Welchen Code soll ich in .bashrc schreiben, damit dies erreicht wird?

Antworten:


10

Diese Funktion sollte den Job erledigen:

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

Gute Antwort! Vergessen Sie nicht, die Funktion mit containernach der Definition aufzurufen .
Rosch

Ich habe erwartet, dass dies offensichtlich ist, aber Sie haben Recht, antworten Sie entsprechend aktualisiert.
Juli

@jlliagre Ich habe den Code ausprobiert. Es funktioniert reibungslos auf dem Gnome-Terminal, aber auf Guake gibt es ein Problem. Es gibt keine Ausgabe. Stattdessen friert es ein wie in einer Sackgasse. Ich muss Strg + C drücken, um es zu benutzen. Ich habe den Code nicht wirklich verstanden, also weiß ich nicht, wo es schief geht.
VedVals

Code behoben. Ich habe vermisst, dass guake von Python ausgeführt wird und es einen Fehler gab, der das Beenden der Funktion verhinderte. Danke für die Rückmeldung.
Juli

Sorry Alter, funktioniert immer noch nicht ganz. Gibt Fehler bash: [: too many arguments. Habe bash v4.2.24, python v2.7.3 wenn es hilft.
VedVals

10

Versuche dies:

echo $TERM

Dies ist maßgeblicher, kann jedoch von Ihren Programmen durcheinander gebracht werden. Allerdings steht auf meinem xtermund auf ttys linux, was meiner Meinung nach für Linux Console steht.


2
$TERMist eine Variable, die sich auf die Spezifikation bezieht, die vom verwendeten Terminal-Emulator selbst gemeldet wurde, nicht auf den eigentlichen Emulator. Beispielsweise echo $TERMkehrt auf meinem System zurück xterm, obwohl ich tatsächlich lxterminal ausführe. Was gerade passiert, ist die lxterminale Selbstmeldung der xterm Compliance. lxterminal ist nicht vollständig xterm-konform, Sie müssen also aufpassen. Die Spezifikationsdateien befinden sich normalerweise in /usr/share/terminfo.
Stazher

7

Sie können den Namen des Terminalemulators abrufen, indem Sie den Namen des übergeordneten Prozesses angeben. Daher funktioniert es mit jedem Terminalemulator.

In bash, zsh usw .:

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

Mit Fischschale:

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

Beachten Sie jedoch, dass dies Programmargumente auffängt, wenn der Terminalemulator mit ihnen gestartet wird.
Robobenklein

Funktioniert das, wenn ich über SSH verbunden bin?
user3731622

@ user3731622 wird es nicht! Sie müssen es vom Client weiterleiten.
Enrico

2

Auf vielen Linux - System echo $TERMRückkehr xtermsiehe stazher Beitrag oben.

Gehen Sie folgendermaßen vor, um das eigentliche Terminal in Betrieb zu nehmen:

1: Schließen Sie alle aktuell ausgeführten Terminalinstanzen.

2: Öffnen Sie das neue Terminal wie gewohnt.

3: Befehl wie folgt eingeben:

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

4: Return sollte etwa so aussehen:

lxterminal --geometry=135x20

Hier ist eine Aufschlüsselung:

Also: psist "Prozessstatus"

Die Option ps -oist Mit der durch Leerzeichen oder Kommas getrennten Liste der angegebenen Schlüsselwörter verknüpfte Informationen anzeigen. Klingt kompliziert, ist aber nicht wirklich. (Leerzeichen oder Komma) getrennt (Liste der Schlüsselwörter) angegeben.

(Liste der Schlüsselwörter) ist also 'cmd='nur ein Schlüsselwort in der Liste. Bitten Sie einfach darum, den Befehl zum Öffnen des Terminals anzuzeigen.

ps-Option -pist "nach Prozess-ID" Wow, das ist eine sehr schöne Option für ps. Das Problem ist, dass Sie diese Prozess-ID an ps übergeben müssen. Wie bekomme ich die Prozess-ID? Wir packen den Ausdruck aus $(ps -o 'ppid=' -p $$)

Hier müssen wir anfangen, etwas tiefer zu denken. Ich wünschte, ich hätte diesen Bash-Einzeiler erfunden, aber ich tat es nicht. Ich glaube, ich habe es irgendwo von https://wiki.archlinux.org/ gestohlen , ich konnte es nicht wiederfinden. Diese Jungs sind großartig, aber oft kann ich nicht verstehen, was sie zu tun sagen, bis sie viel gelernt haben. Was wir tun können, ist es jetzt zu verstehen, weil ich es erklären werde.

Wir wissen $also, dass Expansionsoperator in der Bash ist. Ich denke gerne "auspacken". Also $(foo -opt bar)wird "foo -opt bar" ausgepackt oder erweitert. Aber in der Bash (...)öffnet eine einzelne runde Klammer die Unterschale.

So $(foo -opt bar)erweitert "foo -opt bar" als Lauf in Tochter Shell . Sehr seltsam und schwer zu verstehen.

OK, jetzt führen wir wieder einen fast identischen Befehl aus, ps -o 'ppid=' -p $$aber dieses Mal zeigt uns ps, process status, was er in der Instanz der Tochter-Shell sehen kann .

-oListe der Schlüsselwörter, nur ein Schlüsselwort wie zuvor, aber ppid=dies fragt direkt nach der Prozess-ID der übergeordneten Shell !! Aus INNERHALB DER TOCHTERSCHALE! Sehr schlau, ja? Ich bin so aufgeregt, wenn ich das verstehen kann!

-pAuch hier steht "by process id" und in bash $$die Prozess-ID.

Wenn Sie ps -o 'ppid=' -p $$oder einen anderen Befehl aufrufen , der $$direkt von der ersten Shell angefordert wird, könnte er pid = 1 oder die pid von xWindow oder Ihrem Desktop-Programm sagen, oder Sie erhalten möglicherweise die tatsächliche pid der Shell. Wenn Sie mehrmals fragen, erhalten Sie möglicherweise jedes Mal eine andere Antwort!

Aber wenn Sie eine Tochter anrufen und sie fragen, wer Ihr Vater ist, wird sie es Ihnen sagen! Sehr schlau. Ich wünschte, ich könnte solch ein Genie sein, um diese Methode zu erfinden.


OK, so dass AU keine ordnungsgemäße Aufschlüsselung innerhalb eines Beitrags zulässt. Entschuldigung, ich bin nicht bereit, mit dem Blogsystem zu kämpfen und mehrere Beiträge zu verfassen. Vielleicht können Sie sich ein Bild machen.
Stazher

Ihre andere Antwort scheint eher ein differenzierter und informativer Kommentar zu dieser Antwort als eine Antwort auf die Frage zu sein vollständig beantwortet die Frage. Mit ---- eine Linie in die Mitte ziehen? Es gibt auch einen Knopf.
Zanna

Ich glaube, ich habe die OP-Frage genau und ausführlich beantwortet. Du bist auf mich gesprungen, bevor ich die Chance hatte, das Blog-Bearbeitungssystem zu verstehen und fertig zu werden. Bring die Stimmen runter, ich bin daran gewöhnt.
Stazher

1
Ich glaube nicht, dass ich auf dich gesprungen bin, ich habe gerade eine Rezension gemacht ... danke, dass du deinen Beitrag vervollständigt hast
Zanna

Danke für Ihre Antwort. Es tut mir leid, vielleicht bin ich auf dich gesprungen. Ich entschuldige mich sehr.
Stazher

1

Verwenden pstreeund awkist der einfachste Weg:

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

Erklären

  1. Zeigen Sie einen Prozessbaum mit pstreeof $$(dem aktuellen Prozess) an.
  2. Die pstreeArgumente:

    • -s: Zeigt die Eltern eines Prozesses an
    • -A: Ausgabe in reinem ASCII anzeigen.
  3. Das awkTool scannt ein Muster und -FArgument wird verwendet, um die Prozesse zu teilen.

  4. Schließlich '{ print $2 }'wird festgelegt, dass awknur das 2. Übereinstimmungsmuster (in diesem Fall der Name des Terminalemulators) ausgegeben werden soll.

Bist du dir sicher $2? In meinem Fall ist das, in das geleitet awkwird, tatsächlich systemd---lightdm---lightdm---upstart---gnome-terminal----bash---pstree...
Enrico Maria De Angelis

@EnricoMariaDeAngelis Ya. Vielen Dank für Ihre Beobachtung. In meinem Fall wird der Terminal-Emulator direkt im systemd-Dienst initialisiert. Ich überprüfe noch einmal den Code und bearbeite ihn mit einer Korrektur.
Silvadev

Dies funktioniert nicht, wenn ich zum Starten des Emulators eine Tastenkombination verwende. Auf XFCE bekomme ich xfsettingsdanstelle des Terminals, das ich benutze.
Michael Hoffmann

Funktioniert besser, wenn Sie am Ende beginnen:pstree -sA $$ | head -n1 | awk -F "---" '{ print $(NF-1) }'
Ab dem

0

Sie haben Recht, ich habe nur die Überschriftenfrage beantwortet, nicht die Frage im Text. Also los, und Bob ist dein Onkel.

Ich bin mir nicht sicher, worum es bei dem Fallwechsel ging, wie oben in einer Antwort gezeigt. Ein solcher Fallschalter ist nicht erforderlich. Mein ~ / .bashrc-Skript ist eigentlich nur eine einfache Zeile, alle Echo-Befehle dienen nur dem Spaß. Wie erklärt man...

Jeder Begriff liest beim Starten ~ / .bashrc und führt alle Befehle aus, die er in .bashrc sehen wird. Unabhängig davon, welcher Begriff aufgerufen wird, liest er .bashrc und führt die Befehle aus. In .bashrc ist daher nur die Struktur erforderlich, um das Verhalten des einen oder anderen Begriffs zu ändern oder auszuschließen. Gewünschtes Verhalten ist, dass jeder Term den gleichen Befehl ausführt, daher ist der case-Schalter nicht erforderlich. Terminal selbst wird Ihnen mitteilen, wie er angerufen wurde, sodass keine Unterscheidung erforderlich ist.

Anmerkung (1) Ich habe nicht auf Guake getestet, aber es funktioniert für alle anderen, die in der ersten Antwort von jlliagre erwähnt wurden.

Hinweis (2) Aufgrund der Formatierung im Markdown für Wiki können Sie nicht wie gezeigt ausschneiden und einfügen. Sie müssen jedes Backtick löschen , einschließlich der unterstrichenen Zeichen, und das tatsächliche Backtick ohne Leerzeichen vor psoder nach dem hinzufügen -p $$).

Skript für ~ / .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."

Das hat viel Spaß gemacht. Ich habe dies zu meinem eigenen ~ / .bashrc hinzugefügt.


per Note (1), habe auf Tilda getestet, funktioniert einwandfrei. Guake ähnelt Tilda, ist aber in Python geschrieben, daher weiß ich immer noch nichts über Guake.
Stazher

0

Wenn Sie Bash verwenden, hilft Ihnen dieser Befehl:

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


0

Wenn Sie ZSH verwendet haben, gibt es eine bessere (schnellere) Lösung, die nur ZSH-integrierte Funktionen verwendet und /proc/$pid/{stat,cmdline}direkt manipuliert .

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
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.