Jak mogę uzyskać nazwę bieżącego terminala z wiersza poleceń?


25

Czy istnieje możliwość uzyskania typu terminala za pomocą polecenia?

Jeśli używam gnome-terminal, wyjście powinno być gnome-terminallub coś podobnego. Przydałaby się również wersja terminalu.

Aktualizacja

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

wyświetli coś takiego:

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

Będzie to również działać z Xterm, ale jak uzyskać tylko nazwę ( xfce4-terminalw tym przypadku)?


Właśnie zaktualizowałem swoją odpowiedź, stosując inne i lepsze podejście. Jeśli masz czas, spójrz i daj mi znać, czy to również działa dla Ciebie.
— terdon

Dzięki, ale pierwszy problem z rxvt -> window 31457282 has no pid associated with it(testowane na Lubuntu)
— TuKsn

O? Cholera, to dziwne. Testowałem pod cynamonem.
— terdon

Odpowiedzi:


29

Orginalna wersja

Jednym ze sposobów na to jest uzyskanie procesu nadrzędnego dla bieżącej sesji powłoki, a stamtąd nazwa terminala.

  1. Uzyskaj element nadrzędny bieżącego procesu powłoki. Zmienna bash $$jest PID twojej bieżącej powłoki, więc możemy podać to jako zapytanie do ps( -p $$) i poprosić go, aby wydrukował PID procesu nadrzędnego ( -o ppid=trailing =ma na celu uniknięcie drukowania nagłówków kolumn):

    $ ps -p $$ -o ppid=
    544
    

    Tak więc PID rodzica mojej powłoki to 544.

  2. Pobierz proces powiązany z tym PID i wydrukuj jego wiersz poleceń

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

    Powyższe dane wyjściowe będą zależeć od używanego emulatora terminala, którego używam terminator.

  3. Połącz wszystko w jednym poleceniu

    ps -p $(ps -p $$ -o ppid=) o args=
    
  4. Użyj tego, aby uzyskać wersję

    $(ps -p $(ps -p $$ -o ppid=) o args=) --version
    terminator 0.97
    
  5. Dodaj do swojej funkcji małą funkcję, ~/.bashrcktóra zwraca nazwę i wersję używanego emulatora terminala (działa to w przypadku większości popularnych emulatorów terminali):

    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}')    
    }

    Możesz teraz uzyskać nazwę terminala, a także przekazać dowolną opcję, którą lubisz (np --version.

Niektóre przykłady z wykorzystaniem różnych terminali:

  1. xterm

    $ which_term
    XTerm(297)
    
  2. terminator

    $ which_term 
    terminator 0.97
    
  3. rxvtTen jeden ma żaden z -V, -versionlub --versionflagi więc nie ma informacji wersja zostanie wydrukowany.

    $  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 <benny@xfce.org>
    and Nick Schermer <nick@xfce.org>.
    
    Please report bugs to <http://bugzilla.xfce.org/>.
    

Nowe i ulepszone

Powyższe podejście nie jest jednak tak godne zaufania. Dusi się, gdy uruchomisz powłokę po suwysłaniu wiadomości do innego użytkownika lub gdy twój terminal jest aliasowany do czegoś i różnych innych przypadków. Ponieważ oczywiście pracujemy tutaj z programami X, lepszym sposobem może być użycie czegoś takiego xdotool(instalowanego z sudo apt-get install xdotool), aby uzyskać informacje:

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

Powyżej wydrukuje wiersz poleceń użyty do uruchomienia aktualnie aktywnego okna. Ponieważ twój terminal prawdopodobnie będzie aktywny, to polecenie, które pokaże. Oznacza to, że w przypadku większości emulatorów terminali można bezpiecznie założyć, że zwrócone 1. pole to nazwa terminala:

$ which_term 
lxterminal 

Oznacza to, że uzyskanie wersji jest banalne. Na przykład

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

Nie dotyczy to gnome-terminal:

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

lub terminator:

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

Możemy więc uczynić to nieco bardziej złożonym (tutaj są pewne bashizmy, ten nie jest przenośny):

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"
}

Działa to we wszystkich przypadkach, w których testowałem.


@ Xubu-Tur hmm, próbowałem tylko uruchamiając każdy terminal z innego terminala ręcznie i działało dobrze. Domyślam się, że menu środowiska pulpitu mają inną ścieżkę lub w jakiś sposób różnią się sposobem uruchamiania terminali. Mogę dać ci coś lepszego, jeśli powiesz mi dokładnie, jak je uruchomiłeś i jaki masz błąd. Jeśli uruchomiłeś z menu, sprawdź, jakie polecenie uruchamia element menu.
— terdon

@ Xubu-Tur nie dodawaj zrzutu ekranu. Po prostu wklej komunikat o błędzie do swojego pytania. To samo dla każdego polecenia, które uruchamia element menu. Nie oczekuj, że ręcznie skopiuję go ze zdjęcia!
— terdon

2
Możesz po prostu użyć, $PPIDaby uzyskać PID procesu nadrzędnego.
— nyuszika7h

@ nyuszika7h tak, możesz i +1 za to, ale wolałbym nie. Właśnie sprawdziłem i nie jest dostępny w kshlub tcsh. Jest to jednak bardzo dobry pomysł dla rodziny bash, ponieważ jest to znacznie prostsze niż moje podejście.
— terdon

Jest zdecydowanie dostępny w ksh93i mksh.
— nyuszika7h

8

Spróbuj tego,

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

LUB

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

Pierwszy zawiedzie, rxvta terminatordrugi zawiedzie uxtermi gnome-terminal(drukuje /usr/lib/gnome-terminal/gnome-terminal-server). Wszystkie zawiodą (podobnie jak moje), jeśli używasz sesji su.
— terdon

7
basename "$(cat "/proc/$PPID/comm")"

$PPIDjest PID procesu macierzystego powłoki. commoznacza polecenie . Może to być pełna ścieżka, ale basenamew razie potrzeby używamy jej do usuwania.

Ostrzeżenia

Prawdopodobnie dotyczą one przynajmniej niektórych innych odpowiedzi.

  • commjest technicznie argv[0], co w rzeczywistości może być dowolnym ciągiem. Ale ogólnie powinieneś być w stanie polegać na tym w tym konkretnym przypadku.

  • To nie będzie działać, jeśli połączyć się przez SSH lub wykorzystania zgodnie z oczekiwaniami tmux, screenlub coś podobnego.


To jest bardzo fajne +1, ale na terminalu terminatora dostaję tylko terminjako wynik.
— TuKsn

Nie wiem dlaczego, to pewnie wina Terminatora.
— nyuszika7h

To dlatego, że myślę, że jest uruchamiany jako skrypt Pythona. To jest naprawdę denerwujące.
— terdon

Pamiętaj, że $PPIDnie jest to standard we wszystkich powłokach. np. tcshdostaję:PPID: Undefined variable.
— arielf

2

Możesz spróbować wykonać następujące polecenie:

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

Aktualizacja (dzięki OP i 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

Myślę, że chce to wiedzieć podczas aktywnej sesji terminalu :) Więc jeśli używa w tym czasie „szpachli” ...
— Rinzwind

Nie, nie „putty”, ale co z Xterm, dzięki temu poleceniu dostaję się także gnome-terminal 3.6.2-0ubuntu1ldo Xterm?
— TuKsn

2
Nie drukuje to terminalu, którego obecnie używasz. Drukuje wszystko, co zostało ustawione jako domyślny $ COLORTERM, który nie ma nic wspólnego z tym, czego używasz w tym czasie.
— terdon

Aktualizacja działa dobrze również z Xterm i pokazuje wersję i nazwę.
— TuKsn

Cały kredyt należy do @Avinash, a ty za właściwe polecenie. Właśnie dodałem wersję.
— Sylvain Pineau

2

Inną (nie idealną) możliwością jest:

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

Ale to nie działa z lxterminal, ponieważ zmienna środowiskowa jest $WINDOWIDpusta ...

Terminator pokazuje nazwę „x-terminal-emulator”.


0

Bieżący terminal można również wykryć za pomocą sekwencji ucieczki: Atrybuty urządzenia (drugorzędne DA)

Na przykład w bash:

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

Zwraca tylko jakiś identyfikator - i niestety nie znam oficjalnej listy, która tłumaczy je na rzeczywiste nazwy.


Aby zobaczyć prawdziwą implementację, która tłumaczy niektóre znane identyfikatory na nazwy terminali, zobacz ten przykładowy skrypt bash: https://github.com/mintty/utils/blob/master/terminal

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.