Jak sprawdzić, który emulator terminala jest aktualnie używany?


15

Mam zainstalowany gnome-terminal i Guake. Chcę podać różne komunikaty startowe, które będą wyświetlane na emulatorach terminali podczas ich uruchamiania. Jaki kod powinienem napisać w .bashrc, aby to osiągnąć?

Odpowiedzi:


10

Ta funkcja powinna wykonać zadanie:

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

Niezła odpowiedź! Nie zapomnij o wywołaniu funkcji containerpo definicji.
rosch

Spodziewałem się, że to będzie oczywiste, ale masz rację, odpowiedź została odpowiednio zaktualizowana.
jlliagre

@jlliagre Próbowałem kodu. Działa płynnie na terminalu gnome, ale ma problem z Guake'em. Nie daje żadnych wyników. Zamiast tego zawiesza się jakby w impasie. Muszę użyć Ctrl + C, aby go użyć. Naprawdę nie rozumiem kodu, więc nie wiem, gdzie idzie źle.
VedVals,

Kod naprawiony. Brakowało mi guake jest uruchamiany przez python i miał błąd uniemożliwiający wyjście z funkcji. Dziękujemy za opinię.
jlliagre

Przepraszam stary, wciąż nie do końca działam. Daje błąd bash: [: too many arguments. Dostałem bash v4.2.24, python v2.7.3, jeśli to pomaga.
VedVals,

10

Spróbuj tego:

echo $TERM

Jest to bardziej autorytatywne, ale może zostać pomieszane przez twoje programy. Jednak w moim przypadku jest napisane, xtermaw ttys - co linux, jak sądzę, oznacza Linuksową konsolę.


2
$TERMjest zmienną, która odnosi się do specyfikacji zgłoszonej przez emulator terminala, którego używasz, a nie do samego emulatora. Na przykład w moim systemie echo $TERMzwraca, xtermmimo że faktycznie uruchomiłem lxterminal. To, co się dzieje, to samodzielne raportowanie zgodności xterm. lxterminal nie jest w pełni zgodny z xterm, więc musisz uważać. Pliki specyfikacji zwykle znajdują się w /usr/share/terminfo.
stazher

7

Nazwę emulatora terminala można uzyskać, wpisując nazwę procesu nadrzędnego. Dlatego działa z każdym emulatorem terminala.

W bash, zsh itp .:

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

Ze skorupką ryby:

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

Należy jednak pamiętać, że spowoduje to przechwycenie argumentów programu podczas uruchamiania emulatora terminala z nimi.
Robobenklein

Czy to działa, jeśli jestem połączony za pomocą SSH?
user3731622,

@ user3731622 nie będzie! Będziesz musiał przekazać go klientowi.
Enrico,

2

W przypadku wielu systemów linuksowych echo $TERMpowrót xtermpatrz wyżej post.

Aby uzyskać faktyczny terminal w użyciu, wykonaj następujące czynności:

1: Zamknij każdą aktualnie uruchomioną instancję terminala.

2: Otwórz nowy terminal przy użyciu zwykłej metody.

3: Wpisz polecenie w następujący sposób:

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

4: Powrót powinien być taki:

lxterminal --geometry=135x20

Oto podział:

Więc: psjest „stanem procesu”

Opcja ps -oto Wyświetl informacje związane z podaną listą słów kluczowych oddzielonych spacjami lub przecinkami. Brzmi skomplikowanie, ale tak naprawdę nie jest. (spacja lub przecinek) oddzielone (lista słów kluczowych).

Tak więc (lista słów kluczowych) jest 'cmd='tylko jednym słowem kluczowym na liście. Tak, po prostu prosi o wyświetlenie polecenia, aby otworzyć terminal.

opcja ps -pto „według id procesu” Wow, to jest bardzo fajna opcja dla ps. Problem polega na tym, że musisz przekazać do ps ten identyfikator procesu. Jak uzyskać identyfikator procesu? Odwijamy wyrażenie $(ps -o 'ppid=' -p $$)

Tutaj musimy zacząć myśleć nieco głębiej. Szkoda, że ​​nie wymyśliłem tego bash-one-liner, ale nie zrobiłem tego. Chyba go ukradłem gdzieś https://wiki.archlinux.org/ , nie mogłem znaleźć ponownie. Ci faceci są niesamowici, ale wiele razy nie rozumiem, co mówią, dopóki nie przestaną dużo się uczyć. Co możemy zrobić, to zrozumieć to teraz, ponieważ wyjaśnię.

więc wiemy, że $jest operatorem ekspansji w bash. Lubię myśleć „un-wrap”. Tak więc $(foo -opt bar)rozpakuje lub rozwinie „pasek opcji foo -opt”. Ale w skrócie, pojedynczy okrągły klamra(...) otwiera podpowłokę.

Tak, $(foo -opt bar)rozszerza „foo -opt bar” w biegu w powłoce córki . Bardzo dziwne i trudne do zrozumienia.

OK, więc teraz ponownie uruchamiamy prawie identyczne polecenie, ps -o 'ppid=' -p $$ale tym razem ps, status procesu, pokazuje nam, co widzi z poziomu instancji powłoki córki .

-olista słów kluczowych, tylko jedno słowo kluczowe jak poprzednio, ale ppid=pyta bezpośrednio o identyfikator procesu powłoki nadrzędnej !! OD WEWNĘTRZNEJ SKÓRY CÓRKI! Bardzo sprytne, tak? Jestem bardzo podekscytowany, kiedy mogę to zrozumieć!

-pponownie „id procesu” i bash $$to identyfikator procesu.

Jeśli zadzwonisz ps -o 'ppid=' -p $$, lub jakakolwiek inna komenda, która prosi $$bezpośrednio o pierwszą powłokę, może powiedzieć pid = 1, pid z xWindow lub z twojego programu komputerowego, albo możesz uzyskać rzeczywisty pid powłoki. Jeśli pytasz wiele razy, za każdym razem możesz otrzymać inną odpowiedź!

Ale jeśli wezwiesz córkę i zapytasz ją „Who's your Daddy”, ona ci powie! Bardzo mądry. Chciałbym być genialny, jeśli chodzi o wynalezienie tej metody.


OK, więc AU nie pozwoli na prawidłowy podział w ramach jednego postu. Przepraszamy, ale nie chcę walczyć z systemem blogów i zamieszczać wielu postów. Może wpadniesz na pomysł.
stazher

Twoja druga odpowiedź wydaje się być wyrafinowanym i pouczającym komentarzem do tej odpowiedzi, a nie odpowiedzią na pytanie ... Byłoby wspaniale, gdybyś mógł połączyć dwie odpowiedzi w jedną i usunąć jedną z nich, a następnie dodać ją tak, aby w pełni odpowiada na pytanie. Użyj ----, aby narysować linię pośrodku? Jest też przycisk.
Zanna

Myślę, że dokładnie i szczegółowo odpowiedziałem na pytanie OP. Skoczyłeś na mnie, zanim zdążyłem zrozumieć system edycji bloga i dokończyć. Oddajcie głosy oddane, jestem do tego przyzwyczajony.
stazher

1
Nie sądzę, że cię skoczyłem, właśnie robiłem recenzję ... dzięki za uzupełnienie twojego postu
Zanna

Dziękuję za odpowiedź. Przepraszam, może skoczyłem na ciebie. Przepraszam bardzo
stazher

1

Korzystanie pstreei awkjest najłatwiejszym sposobem:

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

Wyjaśnianie

  1. Wyświetl drzewo procesów za pomocą pstreeof $$(proces atualny).
  2. Te pstreeargumenty:

    • -s: wyświetl rodziców procesu
    • -A: wyświetla dane wyjściowe w czystym ASCII.
  3. awkNarzędzie skanuje wzór i -Fargumentem jest używany do dzielenia procesów.

  4. Na koniec '{ print $2 }'każe awkwypisać tylko 2. wzorzec dopasowania (w tym przypadku nazwę emulatora terminala).

Jesteś tego pewien $2? W moim przypadku chodzi o awkto, że systemd---lightdm---lightdm---upstart---gnome-terminal----bash---pstree...
Enrico Maria De Angelis,

@EnricoMariaDeAngelis Ya. Dziękuję za twoją obserwację. W moim przypadku emulator terminala inicjuje się bezpośrednio w usłudze systemd. Ponownie sprawdzam kod i edytuję go z poprawką.
silvadev

To nie działa, gdy używam skrótu klawiaturowego do uruchomienia emulatora. W XFCE dostaję xfsettingsdzamiast używanego terminala.
Michael Hoffmann

Działa lepiej, jeśli zaczynasz od końca:pstree -sA $$ | head -n1 | awk -F "---" '{ print $(NF-1) }'
lleaff,

0

Masz rację, odpowiedziałem tylko na główne pytanie, a nie na pytanie w treści. Proszę bardzo, a wujek Boba.

Nie jestem pewien, o co chodziło w przełączniku skrzynek, w jednej odpowiedzi pokazanej powyżej. Taki przełącznik skrzynek nie jest potrzebny. Mój skrypt ~ / .bashrc jest właściwie tylko jedną prostą linią, wszystkie polecenia echa są po prostu dla zabawy. Jak to wyjaśnić...

Każdy termin na początku czyta ~ / .bashrc i wykonuje wszystkie polecenia, które zobaczy w .bashrc. Tak więc, bez względu na to, jaki termin się nazywa, odczyta .bashrc i wykona polecenia, więc tylko struktura potrzebna w .bashrc polegałaby na modyfikacji zachowania lub wykluczeniu jednego lub drugiego terminu. Pożądanym zachowaniem jest wykonanie każdego polecenia w celu wykonania tego samego polecenia, więc zmiana wielkości liter nie jest wymagana. Sam terminal powie ci, jak został powołany, więc nie ma potrzeby różnicowania.

Uwaga (1) Nie testowałem pod kątem guake, ale działa na wszystkie inne wymienione w pierwszej odpowiedzi przez jlliagre.

Uwaga (2) Ze względu na formatowanie w wiki dla wiki, nie możesz wycinać i wklejać jak pokazano. Musisz usunąć każdy backtick , w tym, aby usunąć podkreślone znaki, i dodać rzeczywisty backtick, bez spacji przed pslub po -p $$).

skrypt dla ~ / .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."

To była świetna zabawa. Dodałem to do własnego ~ / .bashrc.


zgodnie z uwagą (1), przetestowane na Tilda, działa dobrze. Guake jest podobny do Tilda, ale jest napisany w pythonie, więc nadal nie wiem o Guake.
stazher

0

jeśli używasz bash, myślę, że to polecenie pomoże ci:

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


0

Jeśli korzystasz z ZSH, istnieje lepsze (szybsze) rozwiązanie, które wykorzystuje tylko wbudowane ZSH i manipuluje /proc/$pid/{stat,cmdline}bezpośrednio.

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
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.