Kaç tane deniz kabuğunun derin olduğumu nasıl bilebilirim?


40

Bazen vim den bir alt kabuk başlatmak gibi şeyler yapıyorum :sh. exitBeni sadece bir seviye geri döndürecek bir alt kabuğumda olduğumu , vs. en dış kabuğumda exitolduğumu ve oturumu kapatacağım veya oturumu kapatacağımı nasıl bilebilirim .

Döndürebileceğim bir çeşit Başlangıç ​​totem veya kaç seviye derin olduğumu bilecek bir şey var mı?



1
Selam! Bir deniz kabuğu altında olup olmadığını görmek için hızlı bir yoludur echo $0. Üst düzey kabuk ise, muhtemelen bir tire ile başlayacaktır. (Bu, en azından bash için doğrudur ve çizgi, sözde bir giriş kabuğu olduğu anlamına gelir.)
jpaugh,

Yanıtlar:


40

Komutu kullanabilirsiniz pstree(varsayılan olarak Ubuntu ile birlikte gelir). Örnek: - şu anda WSL'de yalnızca bir tane açık uçbirim penceresi açıyorum:

User@Wsl:~$ pstree
init─┬─init───bash───pstree
     └─{init}

User@Wsl:~$ bash
User@Wsl:~$ sh
$ bash
User@Wsl:~$ pstree
init─┬─init───bash───bash───sh───bash───pstree
     └─{init}

Gerçek bir Linux / Ubuntu ortamında, işlem ağacı daha karmaşık olacaktır. Ağacı, -sseçilen bir sürecin ebeveynlerine gösterecek seçeneğe göre filtreleyebiliriz . Bizim komut olabilir Yani pstree -s $$, nerede $$şimdiki PID içeren bir ortam değişkenidir:

User@Ubuntu:~$ pstree -s $$
systemd──lightdm──lightdm──upstart──gnome-terminal-──bash──pstree

User@Ubuntu:~$ bash
User@Ubuntu:~$ sh
$ bash
User@Ubuntu:~$ pstree -s $$
systemd──lightdm──lightdm──upstart──gnome-terminal-──bash──bash──sh──bash──pstree

Referanslar:


Kabuk istemine gösterge ekleyin: @ waltinator fikrine göre , seviye bir den daha derinken birkaç farklı mermi için istemin önünde bir sayaç olması için, demonun altında gösterilen satırları ekledim. İlgili run commands ( ~/.*rc) dosyalarının altında.

Gnome-terminal, tty ve ssh oturumunda WSL, Ubuntu 16.04, Ubuntu 18.04 (sunucu / masaüstü), Ubuntu 19.04 üzerinde testler yaptım. İşte bu nasıl çalışır:

görüntü tanımını buraya girin

Sınırlama şudur: sayaç, işletim sistemine bağlı olarak yalnızca 13-14 derinlik seviyesinde çalışır. Sebepleri araştırmayı düşünmüyorum :)

  • bash> .bashrc:

    DEPTH=$(($(pstree -s $$ | sed -r 's/-+/\n/g' | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh)\>') - 1))
    if (( DEPTH > 1 )); then PS1=$DEPTH:$PS1; fi
  • cshve tcsh> .cshrc:

    @ DEPTH = `pstree -s $$ | sed -r 's/-+/\n/g' | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh)\>'` - 0
    if ( $DEPTH > 1 ) then; set prompt="$DEPTH":"$prompt"; endif
  • zsh> .zshrc:

    DEPTH=$(($(pstree -s $$ | sed -r 's/-+/\n/g' | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh)\>') - 1))
    if (( DEPTH > 1 )); then PROMPT=$DEPTH:$PROMPT; fi
  • ksh> .kshrc:

    DEPTH=$(($(pstree -s $$ | sed -r 's/\-+/\n/g' | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh)\>') - 0))
    if (( DEPTH > 1 )); then PS1="$DEPTH":"$PS1"'$ '; fi
  • shBu aslında dashUbuntu'da - burada işler biraz karışık ve kablolu (daha fazla bilgi için aşağıdaki referansları okuyun):

    1. Düzenleme ~/.profiledosya ve altta aşağıdaki satırı ekleyin:

      ENV=$HOME/.shrc; export ENV
    2. ~/.shrcAşağıdaki içerikle dosyayı oluşturun, kshayrıca şunu okur $ENV:

      #!/bin/dash
      DEPTH=$(pstree -s $$ | sed -r 's/-+/\n/g' | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh)\>')
      if [ "$0" != 'ksh' ]; then DEPTH=$((DEPTH - 1)); fi
      if [ "$DEPTH" -gt 1 ]; then export PS1='$DEPTH:\$ '; fi

Referanslar:


Derinliği çıkaran bir komut oluşturun: Başka bir seçenek de derinliği çıkaran kabuk komutu oluşturmaktır. Bu amaçla çalıştırılabilir bir dosya oluşturun (bu nedenle sistem genelinde erişilebilir olmalıdır):/usr/local/bin/depth

sudo touch /usr/local/bin/depth
sudo chmod +x /usr/local/bin/depth

Dosyayı favori düzenleyicinizle düzenleyin ve aşağıdaki satırları içeriği olarak ekleyin:

#!/bin/bash

SHELLS='(bash|zsh|sh|dash|ksh|csh|tcsh)'
DEPTH=$(pstree -s $$ | sed -r 's/-+/\n/g' | grep -Ec "\<$SHELLS\>")

if [[ $@ =~ -v ]]
then
        pstree -s $$ | sed -r 's/-+/\n/g' | grep -E "\<$SHELLS\>" | cat -n
fi

echo "DEPTH: $DEPTH"

[[ $DEPTH -gt 1 ]] && exit 0 || exit 1

Yukarıdaki komut dosyası iki seçeneğe sahiptir -vveya --verboseilgili kabukların bir listesini çıkartacaktır. Ve derinliği birden fazla olup olmadığını kontrol edecek bir başka seçenek de buna bağlı olarak geri dönecek exit 0veya exit 1böylece bu şekilde kullanabilirsiniz depth && exit. İşte birkaç kullanım örneği:

User@Ubuntu:~$ depth          # we are at the 1st level - bash
DEPTH: 1
User@Ubuntu:~$ sh           
$ csh                         # we are at the 2nd level - dash
Ubuntu:~% depth               # we are at the 3rd level - csh
DEPTH: 3
Ubuntu:~% ksh
$ depth -v                    # we are at the 4th level - ksh
     1  bash
     2  sh
     3  csh
     4  ksh
DEPTH: 4
$ depth && exit               # exit to the 3rd level - csh
DEPTH: 4
Ubuntu:~% depth && exit       # exit to the 2nd level - dash
DEPTH: 3
exit
$ depth && exit               # exit to the 1st level - bash
DEPTH: 2
User@Ubuntu:~$ depth && exit  # stay at the 1st level - bash
DEPTH: 1
User@Ubuntu:~$ depth && exit  # stay at the 1st level - bash
DEPTH: 1

Diğer çözümlerle kıyaslama: Burada sağlanan yaklaşımların bazı zayıf yönlerini bulmak için biraz zaman harcadım. Aşağıdaki iki durumu hayal edebildim (daha büyük sözdizimi vurgulaması için büyük harflere ihtiyaç vardır):

  • Ne zaman suveya sudo -idahil olanlar:

    User@Ubuntu:~$ ps | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh|su|sudo)\>'
    1
    User@Ubuntu:~$ echo $SHLVL
    1
    User@Ubuntu:~$ depth
    DEPTH: 1
    
    User@Ubuntu:~$ su spas
    Password:
    
    Spas@Ubuntu:~$ ps | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh|su|sudo)\>'
    1
    Spas@Ubuntu:~$ echo $SHLVL
    2
    Spas@Ubuntu:~$ depth
    DEPTH: 2
    
    Spas@Ubuntu:~$ sudo -i
    [sudo] password for spas:
    
    Root@Ubuntu:~# ps | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh|su|sudo)\>'
    3
    Root@Ubuntu:~# echo $SHLVL
    1
    Root@Ubuntu:~# depth
    DEPTH: 3
  • Bir arka plan işlemi başlatıldığında:

    User@Ubuntu:~$ bash
    User@Ubuntu:~$ ps | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh)\>'
    2
    User@Ubuntu:~$ echo $SHLVL
    2
    User@Ubuntu:~$ depth
    DEPTH: 2
    
    User@Ubuntu:~$ while true; do sleep 10; done &
    [1] 10886
    User@Ubuntu:~$ ps | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh)\>'
    3
    User@Ubuntu:~$ echo $SHLVL
    2
    User@Ubuntu:~$ depth
    DEPTH: 2
    
    # Note: $SHLVL is not supported only by sh/dash.  
    #       It works with all other tested shells: bash, zsh, csh, tcsh, ksh
    
    User@Ubuntu:~$ sh
    $ ps | grep -Ec '\<(bash|zsh|sh|dash|ksh|csh|tcsh)\>'
    4
    $ echo $SHLVL
    2
    $ depth
    DEPTH: 3

Benim sistemde var çıkışı hakkında Şimdi şaşkın: systemd───xfce4-terminal───bash───pstree. Neden bu şekilde?
val

1
@ val: systemd init işlemidir, diğer tüm işlemlerin ebeveyni. Sen görünüşte kullandığınız xfce4-terminalbir başlattı, hangi bashkaçtın, içinde kabuk, pstreekendisi ve ailesini bildirdi. Eğer systemd ve xfce4-terminal arasındaki adımların yokluğunu kastediyorsanız, xfce4-terminal'in başlattığı her neyin ölmesi veya reddedilmesi olabilir, bu durumda init tarafından miras alınabilir.
Nick Matteo,

Okumamak için bir sebep var SHLVLmı? Süreçler ve sistemler arasında taşınabilirlik olduğunu varsayıyorum, ancak pstree yüklenmemiş olabilir ..
D. Ben Knoble

Merhaba, @ D.BenKnoble, @ egmont'un cevabı altında tartışıldığı gibi , $SHLVLbazı mermiler tarafından desteklenmemektedir. Daha spesifik olarak, yukarıdaki demodan ortama göre, sadece sh( dash) - tarafından desteklenmez ve bu kabuk bu değişken tarafından sayılmaz. Öte yandan pstreepaketin bir parçası olan psmisc da sağlar fuser, killallve birkaç diğerleri - bu Ubuntu ana bileşenidir - Bu cevapta belirtildiği sistem üzerinde yüklü değil.
pa4080

30

SHLVLKabuk değişkeninin değerini kontrol edin :

echo $SHLVL

bashKılavuz sayfasından alıntı :

SHLVL  Incremented by one each time an instance of bash is started.

Tarafından da desteklenmektedir zsh.


4
Fakat sh sayılmaz, dolayısıyla sh ile verilen örnek SHLVL'yi arttırmazdı. Yine de bu, kabukları çok fazla değiştirmeyenler için faydalı olabilecek bir şeydir
ubfan1

3
@ ubfan1 geçersiz bir vimrc tanımı olmadığı sürece :sh, kullanıcının oturum açma kabuğundaki varsayılanları sanırım ( :shellbelirli bir kabuk ikili adının yerine gerçekten kısaltılmış bir formdur )
steeldriver

3
Ben Vim detaylarına aşina değilim, ama ben denedim :shgelen vimbu cevabı göndermeden önce, ve benim için kabuk seviyesini artırma yaptı. Giriş kabuğum bash.
egmont

9

Benim içinde .bashrc, kullandığım $SHLVLayarlamak için $PS1"ekleyerek, +" Benim işaretleri $SUBSHELLdeğişken:

...
# set a variable to reflect SHLVL > 1 (Ubuntu 12.04)
if [[ $SHLVL -gt 1 ]] ; then
    export SUBSHELL="${SUBSHELL:+$SUBSHELL}+"
else
    export SUBSHELL=""
fi
...

if [[ "$color_prompt" = yes ]]; then
#             chroot?                       Depth      green       user@host nocolor  :   green      $PWD  red      (status) off   $ or # space             
    PS1='${debian_chroot:+($debian_chroot)}${SUBSHELL}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[1;31m\]($?)\[\033[00m\]\$ '
else
    PS1='${debian_chroot:+($debian_chroot)}${SUBSHELL}\u@\h:\w\$ '
fi
...

Sonra ne kadar derin olduğumu görebiliyorum:

walt@bat:~(1)$ ed foo
263
!bash
+walt@bat:~(0)$ bash
++walt@bat:~(0)$ bash
+++walt@bat:~(0)$ exit
exit
++walt@bat:~(0)$ exit
exit
+walt@bat:~(0)$ exit
exit
!
q
walt@bat:~(0)$ 

4

awk:

# Count the occurrence of (sh)ells.
DEPTH_REGEX='^(ash|bash|busybox|csh|dash|fish|mksh|sh|tcsh|zsh)$'

DEPTH=$(/bin/ps -s $(/bin/ps -p $$ -osid --no-headers) -ocomm --no-headers | \
awk -v R=$DEPTH_REGEX '{for (A=1; A<=(NR-2); A++) {if ($A ~ R) {B++}}} END {print B}')

pgrep:

DEPTH=$(/usr/bin/pgrep -c -s $(/bin/ps -p $$ -osid --no-headers) '^(ash|bash|busybox|csh|dash|fish|mksh|sh|tcsh|zsh)$')

İki sürümden birini bir dosyaya yerleştirebilir ve $ DEPTH kullanılabilir duruma getirmek için kaynak kullanabilirsiniz.

# Set 256 colors in terminal.
if [ -x /usr/bin/tput ] && [ "$(SHELL=/bin/sh tput colors)" -ge 8 ]; then
    export TERM="xterm-256color"
fi

# change these if you don't dig my colors!

NM="\[\033[0;1;37m\]"   #means no background and white lines
HI="\[\033[0;37m\]"     #change this for letter colors
SI="\[\033[38;5;202m\]" #this is for the current directory
NI="\[\033[0;1;30m\]"   #for @ symbol
IN="\[\033[0m\]"

# Count the occurrence of (sh)ells.
source /usr/share/shell-depth/depth

PS1="${NM}[${HI}\u${NI}@${HI}\h ${SI}\w${NM} \A](${HI}${DEPTH}${NM}): ${IN}"

2

psTüm kabuk yığınını görmek için (geçerli olanı da dahil olmak üzere) herhangi bir argüman olmadan kullanabilirsiniz . Ayrıca başlattığınız tüm arkaplan işlerini de pskendisinin yanında gösterecek, ancak ne kadar derin olduğunuzun kabaca bir tahminini verebilir.


Bu { echo hello world; ps; } &, psyukarıdaki cevabı kanıtlamak için çalışır .
WinEunuuchs2Unix

@ WinEunuuchs2Unix, şöyle bir şey demek istiyorum: paste.ubuntu.com/p/6Kfg8TqR9V
pa4080

Pstree -s $$ ile ps arasında taklit etmenin bir yolu var mı?
bac0n
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.