Jak wykryć liczbę otwartych terminali przez użytkownika

9

Używam Ubuntu i mogę ręcznie zmienić bashkolor zachęty powłoki na zielony za pomocą

export PS1="\e[0;32m[\u@\h \W]\$ \e[m" 

Chcę jednak, aby kolor zachęty powłoki zmieniał się automatycznie za każdym razem, gdy otwieram nowy terminal lub kartę. Wiem, że podstawowy tty TERM ma 16 kolorów i można obracać kolorami, jeśli więcej niż 16 terminali jest otwartych. Czy rozwiązanie zadziała również, gdy się połączę Putty, tmuxlub screen.

Moim pomysłem jest napisanie skryptu powłoki i umieszczenie go w taki sposób, aby .bashrcwykrywał nową sesję terminala, którą użytkownik otworzył, i zwiększał licznik globalny od \e[0;31m[do \e[0;47m[. Jak wykryć liczbę otwartych terminali przez użytkownika?

manav mn
źródło

Odpowiedzi:

8

Jeśli naprawdę potrzebujesz uzyskać liczbę otwartych terminali, przejdź do zliczania posiadanych plików /dev/pts(chociaż mogą to obejmować pliki otwierane przez procesy w tle, a nie przez emulatory terminali graficznych). Ewentualnie policz liczbę procesów potomnych emulatora terminalu, jak pokazuje Jacob w pierwszym wierszu swojej odpowiedzi.

Unikaj polegania na wynikach whoi szukania gnome-pty-helperprocesów, ponieważ nie działają one w nowszych gnome-terminalwersjach.

Zauważ, że obecnie prawie wszystkie emulatory terminali graficznych (w tym kit) i multipleksery (ekran, tmux) obsługują 256 kolorów. Korzystając z tej palety, możesz uzyskać naprawdę ładne kolorowe podpowiedzi.

Moim zaleceniem dla bardzo prostego rozwiązania jest oparcie koloru na bieżącym numerze linii tty. Np. Przetworzyć wynik ttypolecenia, aby wziąć tylko liczbę i wyprowadzić z niej kolor. Pewny numer linii tty jest podawany tylko do jednego terminala na raz, musisz najpierw zamknąć ten terminal, zanim jądro ponownie wyda ten sam numer linii. To, w połączeniu z 256 kolorami, automatycznie gwarantuje, że nie zobaczysz tego samego koloru dwa razy w danym momencie (a nawet w przypadku 16 kolorów dałoby to dość równomierny rozkład). Nie ma potrzeby utrzymywania globalnego licznika ani zliczania terminali lub procesów.

egmont
źródło
1
Piękny pomysł z tty. Myślę, że my / inni zbytnio skoncentrowaliśmy się na tym „pytaniu” i zapomnieliśmy, że mogą istnieć inne rozwiązania dla całej „potrzeby” :) Bawiłbym się nawet implementacją losowego wyboru koloru. Jeśli jest to 256 kolorów, wybranie takich samych / podobnych kolorów nie powinno się zdarzyć dużo. Jednak ręczne ustawienie kolorów dla danych liczb pts zapewni lepszą personalizację.
GreggD,
@TedM. Tak, pytanie zostało sformułowane raczej jako pytanie XY, w stylu: „Chcę mieć inny kolor w każdym terminalu, więc powiedz mi: jak policzyć liczbę terminali?”
egmont
@TedM. Random to także fajny pomysł! (Jedną z właściwości deterministycznego odwzorowania jest to, że po sudoing nowy użytkownik może łatwo ustawić ten sam kolor zachęty. To może, ale nie musi, to, co chce pierwotny pytający.)
egmont
1
Randomizer jest dość łatwy: color="\e[38;5;"$(((RANDOM % 231 )+1))"m"(tylko 231, aby odrzucić skalę szarości), jednak wiele z tych kolorów miało po prostu różne odcienie, a kilka z nich jest ciemnych, więc może być prawie niewidocznych, a ja sądzę, że nikt nie użyje tego w prawdziwym życiu ...
GreggD
Nie znamy wersji Ubuntu pytającego. W 16.04 zdecydowanie nie ma już gnome-pty-helper ( git.gnome.org/browse/vte/commit/?id=299c700 ). Nie zamierzam obniżyć wersji, aby sprawdzić dokładną hierarchię procesów w starszych wersjach. Wiem, że kiedyś istniał taki proces, ale nie jestem do końca pewien, jak wyglądała hierarchia rodzic-dziecko. Nawiasem mówiąc, wziąłem pomysł liczenia procesów potomnych z twojej oryginalnej odpowiedzi, więc nie rozumiem, że „(również przez ciebie)”, nieważne.
egmont
5

W sytuacji jednego użytkownika, jeśli weźmiemy przykład xterm, możemy po prostu policzyć liczbę pid xterm; xtermtworzy osobny pid dla każdego okna.
gnome-terminaluruchamia jednak pojedynczy pid, ale dobrą wiadomością jest to, że tworzy proces potomny dla każdego okna i / lub karty. możemy pobrać te procesy potomne za pomocą polecenia:

pgrep -P <pid_of_gnome-terminal>

Istnieje jednak kilka komplikacji:

  • Czytając twoje pytanie, możemy założyć, że użytkownik w tym przypadku jest faktycznie właścicielem sesji x . Zwykle możemy po prostu użyć opcji $USER-variable, ale może to nie pasować do aktualnie zalogowanego użytkownika $DISPLAY.

  • W sytuacji wielu użytkowników pidy należące do (której) aplikacji terminalowej niekoniecznie należą do bieżącej $DISPLAY. Musimy oddzielić tylko odpowiednie pids i pids dla dzieci.

  • W Unity (15.10 lub niższej), jeśli zaloguje się drugi użytkownik, uruchamiany jest dodatkowy proces ( gnome-pty-helper), który pojawia się jako proces potomny gnome-terminal, ale proces (oczywiście) nie ma okna ani karty. Na Mate proces i tak istnieje.

W skrócie

Aby policzyć liczbę kart i / lub okien aplikacji terminalowej, musimy:

  • Sprawdź, czy uruchamiamy aplikację terminalową, która ma wiele pidów lub jeden pid na jednej $DISPLAY(sesja x)
  • Z uruchomionych procesów oddzielić tylko odpowiednie stawki, działając na tym$DISPLAY
  • Jeśli aplikacja uruchamia procesy potomne dla swojego identyfikatora pid (dla systemu Windows / kart), sprawdź, czy gnome-pty-helperdziała, aby poprawić liczbę.

Można to jednak dobrze napisać w skrypcie, aby niezawodnie znaleźć liczbę aktualnie otwartych okien i / lub kart.

Scenariusz

W poniższym skrypcie jako argument używana jest docelowa aplikacja terminalowa . Skrypt działa na wielu terminalach, na których go testowałem. W Tildatej chwili jest wyjątek .

Przykład

  • Mam zalogowanych dwóch użytkowników, jeden (nie bieżący) z dwoma gnome-terminaloknami, jeden (jeden na obrazku) z trzema gnome-terminaloknami i dwoma xtermoknami.

wprowadź opis zdjęcia tutaj

Komenda:

/path/to/get_terms.sh gnome-terminal

wyjścia:

3

podczas

/path/to/get_terms.sh xterm

wyjścia:

2

Scenariusz

#!/bin/bash

terminal=$1

# get the user running the current x-session
username=$(who | grep $DISPLAY | head -1 | awk '{print $1}')
# get the pid of the terminal for the current user
userpid=$(pgrep -u $username $terminal)
# check what type the terminal is (multi pid/single pid)
npids="$(echo "$userpid" | wc -w)"
# in case of a single pid, count the children
if [ "$npids" -eq 1 ]; then
  # check if gnome-pty-helper runs (starts when multiple users are logged in)
  ptpid=$(pgrep gnome-pty-helpe)
  # get number of child- procs
  let "orig = $( pgrep -P $(pgrep -u $username $terminal) | wc -w )" 
  # if pty-helper runs, correct the number of child procs
  if [ -n "$ptpid" ] && [ -n "$userpid" ]; then
    let "n_terms = $orig-1"; else let "n_terms = $orig"
  fi
  # if no child procs run, n-terminals = n-counted pids (difference Mate <> Unity)
  if [ "$n_terms" -eq 0 ]; then echo $orig; else echo $n_terms; fi
# in case of multiple pids, count the pids
elif [ "$npids" -gt 1 ]; then echo $npids
fi

Używać

  • Skopiuj skrypt do pustego pliku, zapisz go jako get_terms.sh, wykonaj go i uruchom za pomocą polecenia:

    /path/to/get_terms.sh <terminal_application>
Jacob Vlijm
źródło
Tutaj zawsze mam jeden gnome-pty-helperuruchomiony, nawet gdy zalogowany jest tylko jeden użytkownik (zaraz po ponownym uruchomieniu), a kiedy otwieram dowolną liczbę terminali, działa on drugi, ten sam pomocnik. Twój nowy skrypt wydaje się działać dla mate-terminal (nie był w stanie spowodować tego zerowego), ale w Xterm, gdy mam tylko 1 otwarty, pokazuje 0i zaczyna pokazywać dobrą liczbę dopiero po drugim i z gnome-terminal zawsze pokazuje o jeden za mało (wyjście, 0gdy tylko jeden jest otwarty).
GreggD,
@TedM. Dzięki, to jest użyteczna informacja, naprawiona teraz.
Jacob Vlijm
Naprawdę podziwiam twoją „pasję” :) ... ale wciąż jest problem z terminalem gnome. Jeden daje 1, dwa daje 1, trzy daje 2, cztery daje 3 itd. Dodatkowo moje nowe odkrycie, „Tilda” MATE (ten jeden dodatkowy „nieznany” terminal w mojej odpowiedzi) również ma taki sam problem jak terminal gnome, ale z jego zakładkami. xterm i mate-terminal wydają się jednak działać dobrze.
GreggD
@TedM. Dzięki za wzmiankę! Głupie pytanie, ale czy na pewno używasz najnowszego kodu? Na Mate 15.10 wszystkie testy uruchamiam bez wyjątku. Jaka jest twoja wersja Mate? Na Unity wszystko już działało dobrze.
Jacob Vlijm
@TedM. Również na moim ślicznym pustym Mate 15.10 jest on domyślnie dostępny. Po prostu powtórnie testy, idealnie! czy mogę poprosić cię jutro o uruchomienie edytowanej wersji skryptu i opublikowanie gdzieś wyniku, aby zobaczyć, co powoduje wyjątek w twoim przypadku?
Jacob Vlijm
1

awkSposób:

who | awk 'BEGIN{count=0}{ if(NR!=1){count++} }END{print count}'

Wyjaśnienie:

W powyższym 1 poleceniu linijki awksłuży do znalezienia liczby terminali. Wewnątrz awkprogramu sprawdza tylko liczbę wierszy zwracanych przez komendę - 1.

podejrzeć
źródło
zwraca mi to 0, co jest oczywiście nieprawdą ...
Zanna
Ten działa bardzo dobrze dla mojego mate-terminal & xterm, wydaje się kuloodporny.
GreggD,
W skrócie:, who | awk 'END{print NR - 1}'ponieważ chcesz, aby liczba linii - 1.
muru
0

Prostym sposobem może być również uruchomienie System Monitor(jeśli uruchamiasz z Terminala, musisz napisać gnome-system-monitor) i w zakładce „Procesy” uporządkuj uruchomione procesy według Nazwy, a następnie policz liczbę wystąpień Bashna liście (będą one wszystkie razem, jeśli zorganizujesz według imię, więc łatwo policzyć).

Pamiętaj, że musisz szukać, Basha nie, Gnome Terminaljeśli chcesz zobaczyć liczbę otwartych terminali według użytkownika. Po otwarciu terminal Gnome Terminalpojawi się również na liście procesów, ale pozostanie tylko jeden, nawet jeśli zostanie otwartych więcej terminali. Przycisk „Widok” System Monitorumożliwia ustawienie procesów, które chcesz zobaczyć, np. Wszystkie procesy / procesy użytkownika / aktywne ...

NonStandardModel
źródło
Ponieważ OP chce wykorzystać wynik do automatycznego ustawienia koloru (-ów) terminala, nie wydaje się to naprawdę istotną opcją.
Jacob Vlijm
Przepraszam, widzę, że teraz chce użyć go w skrypcie. Ale wtedy ps -ef | grep nazwa_użytkownika | grep bash | grep -v grep | wc-nie działa?
NonStandardModel