Odpowiedzi:
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
bash: [: too many arguments
. Dostałem bash v4.2.24, python v2.7.3, jeśli to pomaga.
Spróbuj tego:
echo $TERM
Jest to bardziej autorytatywne, ale może zostać pomieszane przez twoje programy. Jednak w moim przypadku jest napisane, xterm
aw ttys - co linux
, jak sądzę, oznacza Linuksową konsolę.
$TERM
jest 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 $TERM
zwraca, xterm
mimo ż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
.
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/^.* //')
W przypadku wielu systemów linuksowych echo $TERM
powrót xterm
patrz 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: ps
jest „stanem procesu”
Opcja ps -o
to 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 -p
to „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 .
-o
lista 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ć!
-p
ponownie „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.
Korzystanie pstree
i awk
jest najłatwiejszym sposobem:
pstree -sA $$ | awk -F "---" '{ print $2 }'
pstree
of $$
(proces atualny).Te pstree
argumenty:
-s
: wyświetl rodziców procesu-A
: wyświetla dane wyjściowe w czystym ASCII.awk
Narzędzie skanuje wzór i -F
argumentem jest używany do dzielenia procesów.
'{ print $2 }'
każe awk
wypisać tylko 2. wzorzec dopasowania (w tym przypadku nazwę emulatora terminala).$2
? W moim przypadku chodzi o awk
to, że systemd---lightdm---lightdm---upstart---gnome-terminal----bash---pstree
...
xfsettingsd
zamiast używanego terminala.
pstree -sA $$ | head -n1 | awk -F "---" '{ print $(NF-1) }'
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 ps
lub 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.
jeśli używasz bash, myślę, że to polecenie pomoże ci:
which $(ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$))
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
}
container
po definicji.