Problem : znajdź głębokość pocisków.
Szczegóły : Często otwieram powłokę z vima. Zbuduj, uruchom i zakończ. Czasami zapominam i otwieram kolejną vimę, a potem kolejną powłokę. :(
Chcę wiedzieć, ile mam głębokich pocisków, być może nawet mam je przez cały czas na ekranie. (Mogę zarządzać tą częścią).
Moje rozwiązanie : parsuj drzewo procesów i poszukaj vim i bash / zsh i oblicz głębokość bieżącego procesu.
Czy coś takiego już istnieje? Nic nie mogłem znaleźć.
$SHLVL
zmienna (obsługiwana przez kilka powłok) jest tym, czego szukasz?fg
wrócić, która nie ma tego problemu.vim
zadań może być bardziej mylące niż stos stosu procesów zagnieżdżonych. Nawiasem mówiąc, wolę mieć wiele okien , więc mogę łatwo skakać szybko tam iz powrotem, ale nie nazwałbym tego problemem XY tylko dlatego, że wolę inny przepływ pracy.Odpowiedzi:
Kiedy przeczytałem twoje pytanie, moją pierwszą myślą było
$SHLVL
. Potem zobaczyłem, że chcesz liczyćvim
poziomy oprócz poziomów powłoki. Prostym sposobem na to jest zdefiniowanie funkcji powłoki:To będzie automatycznie i cicho zwiększać za
SHLVL
każdym razem, gdy wpiszeszvim
polecenie. Musisz to zrobić dla każdego wariantuvi
/vim
, którego kiedykolwiek używałeś; na przykład,Zewnętrzny zestaw nawiasów tworzy podpowłokę, więc ręczna zmiana wartości
SHLVL
nie zanieczyszcza bieżącego (macierzystego) środowiska powłoki. Oczywiściecommand
słowo kluczowe ma zapobiegać wywoływaniu się funkcji (co spowodowałoby nieskończoną pętlę rekurencji). I oczywiście powinieneś umieścić te definicje w swoim.bashrc
lub innym pliku inicjującym powłokę.Powyżej jest niewielka nieefektywność. W niektórych muszlach (bash to jeden), jeśli tak mówisz
gdzie jest zewnętrzny program wykonywalny (tj. nie wbudowane polecenie), powłoka utrzymuje dodatkowy proces leżący w pobliżu, tylko po to, aby czekać na zakończenie. To (prawdopodobnie) nie jest konieczne; zalety i wady są dyskusyjne. Jeśli nie masz nic przeciwko związaniu odrobiny pamięci i gniazda procesu (i zobaczeniu o jeden proces powłoki więcej niż potrzebujesz, gdy wykonujesz a ), to wykonaj powyższe czynności i przejdź do następnej sekcji. To samo, jeśli używasz powłoki, która nie utrzymuje dodatkowego procesu. Ale jeśli chcesz uniknąć dodatkowego procesu, pierwszą rzeczą do wypróbowania jest
cmdn
cmdn
ps
Jest
exec
to polecenie, aby zapobiec dalszemu procesowi powłoki.Ale jest gotcha. Obsługa powłoki
SHLVL
jest nieco intuicyjna: gdy powłoka się uruchamia, sprawdza, czySHLVL
jest ustawiona. Jeśli nie jest ustawiony (lub ustawiony na coś innego niż liczba), powłoka ustawia go na 1. Jeśli jest ustawiony (na liczbę), powłoka dodaje do niego 1.Ale według tej logiki, jeśli tak mówisz
exec sh
,SHLVL
powinieneś pójść w górę. Ale to niepożądane, ponieważ twój rzeczywisty poziom pocisków nie wzrósł. Powłoka radzi sobie z tym, odejmując jedną z następującychSHLVL
czynnościexec
:Więc
jest praniem; zwiększa się
SHLVL
tylko w celu ponownego zmniejszenia. Równie dobrze możesz powiedziećvim
, bez korzystania z funkcji.Aby to naprawić, zrobiłbyś
Potem zobaczyłem, że chcesz liczyć
vim
poziomy niezależnie od poziomów powłoki. Cóż, działa dokładnie ta sama sztuczka (z niewielką modyfikacją):(i tak dalej
vi
,view
itp) Jakexport
to konieczne, ponieważVILVL
nie jest zdefiniowany jako zmiennej środowiskowej domyślnie. Ale to nie musi być częścią funkcji; możesz po prostu wypowiedziećexport VILVL
jako osobne polecenie (w swoim.bashrc
). Jak wspomniano powyżej, jeśli proces dodatkowej powłoki nie stanowi dla ciebie problemu, możeszcommand vim
zamiast tego zrobićexec vim
i zostawić wSHLVL
spokoju:Jeśli używasz powłoki, która nie obsługuje
SHLVL
(np. Myślnik), możesz ją zaimplementować samodzielnie, o ile powłoka implementuje plik startowy. Po prostu zrób coś takiegow twoim
.profile
lub odpowiednim pliku. (Prawdopodobnie nie powinieneś używać nazwySHLVL
, ponieważ spowoduje to chaos, jeśli zaczniesz używać powłoki, która obsługujeSHLVL
).Inne odpowiedzi dotyczyły problemu osadzania wartości zmiennych środowiskowych w zachęcie powłoki, więc nie powtórzę tego, zwłaszcza, że mówisz, że już wiesz, jak to zrobić.
źródło
ps
lubpstree
, kiedy można to zrobić za pomocą wbudowanych powłok.dash
ma rozszerzenie arytmetyczne.SHELL_LEVEL=$((SHELL_LEVEL + 1))
powinno wystarczyć, nawet jeśli $ SHELL_LEVEL był wcześniej rozbrojony lub pusty. To tylko jeśli miał być przenośne do powłoki Bourne, że trzeba by uciekać się doexpr
, ale wtedy trzeba także wymienić$(...)
się`..`
.SHELL_LEVEL=`expr "${SHELL_LEVEL:-0}" + 1`
bash
skrypt do odczytania przez ~ / .bashrc na przykład stdin gniazdo), to może stać się problemem. To dużo „jeśli”, ale coś, o czym warto pamiętać (dane niezanalizowane w kontekście arytmetycznym są niebezpieczne)Możesz policzyć tyle czasu, ile potrzebujesz, aby przejść do drzewa procesów, aż znajdziesz lidera sesji. Podobnie jak w przypadku
zsh
systemu Linux:Lub POSIXly (ale mniej wydajny):
To dałoby 0 dla powłoki, która została uruchomiona przez emulator terminala lub getty, i jedną więcej dla każdego potomka.
Musisz to zrobić tylko raz podczas uruchamiania. Na przykład z:
w swoim
~/.zshrc
lub równoważnym, aby mieć go w swoim podpowiedzi.tcsh
i kilka innych powłok (zsh
,ksh93
,fish
ibash
co najmniej) utrzymywać$SHLVL
zmienną których przyrost na starcie (i ubytku przed uruchomieniem kolejnego polecenia zexec
(chyba, żeexec
jest w podpowłoce, jeśli nie są one buggy (ale wiele z nich))). Śledzi to tylko ilość zagnieżdżenia powłoki , a nie proces zagnieżdżania. Również poziom 0 nie jest gwarantowany jako lider sesji.źródło
Użyj
echo $SHLVL
. Użyj zasady KISS . W zależności od złożoności programu może to wystarczyć.źródło
bash
, ale nie dladash
.Jednym potencjalnym rozwiązaniem jest przyjrzenie się wynikowi
pstree
. Po uruchomieniu w powłoce, która została spawnowana od wewnątrzvi
, część drzewa drzewa, która zawiera listy,pstree
powinna pokazać ci, jak głęboko jesteś. Na przykład:źródło
Pierwszy wariant - tylko głębokość pocisku.
Proste rozwiązanie dla
bash
: dodaj do.bashrc
następnych dwóch wierszy (lub zmień aktualnąPS1
wartość):Wynik:
Liczba na początku łańcucha zachęty będzie oznaczać poziom powłoki.
Drugi wariant, zarówno z zagnieżdżonymi vimami, jak i poziomami powłoki.
dodaj te linie do
.bashrc
Wynik:
v: 1 - poziom głębokości vim
s: 3 - poziom głębokości pocisku
źródło
W pytaniu, o którym wspominałeś, parsowaniu
pstree
. Oto stosunkowo prosty sposób:Te
pstree
opcje:-A
- Wyjście ASCII dla łatwiejszego filtrowania (w naszym przypadku każde polecenie poprzedza`-
)-a
- pokaż również argumenty poleceń, jako efekt uboczny każde polecenie jest wyświetlane w osobnej linii i możemy łatwo filtrować dane wyjściowe za pomocągrep
-l
- nie obcinaj długich linii-s
- pokaż rodziców wybranego procesu(niestety nie obsługiwany w starych wersjach
pstree
)$$
- wybrany proces - PID bieżącej powłokiźródło
To nie jest ścisła odpowiedź na pytanie, ale w wielu przypadkach może to powodować, że nie jest to konieczne:
Po pierwszym uruchomieniu powłoki uruchom
set -o ignoreeof
. Nie wkładaj tego do swojego~/.bashrc
.Przyzwyczaj do pisania Ctrl-D, gdy myślisz, że jesteś w powłoce najwyższego poziomu i chcesz mieć pewność.
Jeśli jesteś nie w górę powłoki poziomie, Ctrl-D zasygnalizuje „koniec wejścia” do bieżącej powłoki i będzie spadać o jeden poziom.
Jeśli są w górnej skorupy poziomu, dostaniesz wiadomość:
Cały czas używam tego do połączonych sesji SSH, aby ułatwić powrót do określonego poziomu łańcucha SSH. Działa również w przypadku zagnieżdżonych muszli.
źródło