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.