मुझे कैसे पता चलेगा कि मैं कितने उप-गोले हैं?


40

कभी-कभी मैं ऐसी चीजों को करता हूं जैसे कि वीम से उप-शेल शुरू करना :sh। मुझे कैसे पता चलेगा कि मैं एक उप-शेल में हूं जहां exitमुझे सिर्फ एक स्तर वापस मिलेगा, exitया सबसे बाहरी शेल में होने के कारण जहां मुझे लॉग आउट किया जाएगा या मेरा सत्र बंद कर दिया जाएगा।

क्या किसी प्रकार का इंसेप्शन टोटेम है जो मैं यह जानने के लिए स्पिन या कुछ कर सकता हूं कि मैं कितने स्तरों पर गहरा हूं?



1
नमस्ते! यह देखने का एक त्वरित तरीका है कि आप किसी सबस्क्रिप्शन में हैं या नहीं echo $0। यदि यह सबसे ऊपर का कवच है, तो यह संभवतः एक डैश के साथ शुरू होगा। (यह कम से कम बैश के लिए सही है, और डैश का अर्थ है कि यह एक तथाकथित लॉगिन शेल है।)
jpaugh

जवाबों:


40

आप कमांड का उपयोग कर सकते हैं pstree(जो कि Ubuntu के साथ डिफ़ॉल्ट रूप से आता है)। यहाँ उदाहरण है - वर्तमान में मैं WSL पर केवल एक खुली टर्मिनल खिड़की रख रहा हूँ:

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}

एक वास्तविक लिनक्स / उबंटू वातावरण में प्रक्रिया पेड़ अधिक जटिल होगा। हम पेड़ को उस विकल्प द्वारा फ़िल्टर कर सकते हैं -sजो एक चयनित प्रक्रिया के माता-पिता को दिखाएगा। तो हमारा कमांड हो सकता है pstree -s $$, जहां $$एक पर्यावरण चर है जिसमें वर्तमान पीआईडी ​​शामिल है:

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

संदर्भ:


शेल के प्रॉम्प्ट में संकेतक जोड़ें: @ वाल्टिनेटर के विचार के आधार पर , कई अलग-अलग शेल के लिए प्रॉम्प्ट के सामने एक काउंटर होने पर जब स्तर एक से अधिक गहरा होता है, मैंने लाइनों को जोड़ा है, जो डेमो के नीचे दिखाया गया है, प्रासंगिक रन कमांड ( ~/.*rc) फ़ाइलों के नीचे।

मैंने WSL, Ubuntu 16.04, Ubuntu 18.04 (सर्वर / डेस्कटॉप), Ubuntu 19.04 पर सूक्ति-टर्मिनल, tty और ssh सत्र के भीतर परीक्षण किए हैं। यहाँ है कि यह कैसे काम करता है:

यहाँ छवि विवरण दर्ज करें

सीमा यह है कि: काउंटर केवल ओएस के आधार पर गहराई के 13-14 स्तरों के लिए काम करता है। मैं कारणों की जांच करने का इरादा नहीं है :)

  • 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
    
  • cshऔर 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
    
  • shयह वास्तव dashमें उबंटू पर है - यहां चीजें थोड़ी जटिल हैं और वायर्ड हैं (अधिक जानकारी के लिए नीचे दिए गए संदर्भ पढ़ें):

    1. ~/.profileफ़ाइल को संपादित करें और नीचे दी गई पंक्ति जोड़ें:

      ENV=$HOME/.shrc; export ENV
    2. ~/.shrcनिम्नलिखित सामग्री के साथ फ़ाइल बनाएँ , नोट kshयह भी पढ़ता है $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
      

संदर्भ:


एक कमांड बनाएं जो गहराई को आउटपुट करेगा: एक अन्य विकल्प शेल कमांड बनाना है जो गहराई को आउटपुट करेगा। इस प्रयोजन के लिए निष्पादन योग्य फ़ाइल बनाएं (इस प्रकार यह सुलभ प्रणाली चौड़ी होनी चाहिए):/usr/local/bin/depth

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

फ़ाइल को अपने पसंदीदा संपादक के साथ संपादित करें और उसकी सामग्री के रूप में निम्न पंक्तियाँ जोड़ें:

#!/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

उपरोक्त स्क्रिप्ट में दो विकल्प हैं -vया --verboseयह शामिल गोले की सूची का उत्पादन करेगा। और दूसरा विकल्प जो यह जांच करेगा कि क्या गहराई एक से अधिक है और इसके आधार पर यह वापस आएगा exit 0या exit 1, इसलिए आप इसे इस तरह से उपयोग कर सकते हैं depth && exit। यहां उपयोग के कुछ उदाहरण दिए गए हैं:

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

अन्य समाधानों की तुलना: मैंने यहां दिए गए दृष्टिकोणों की कुछ कमजोरियों का पता लगाने के लिए कुछ अतिरिक्त समय बिताया। मैं निम्नलिखित दो मामलों की कल्पना करने में सक्षम था (बेहतर सिंटैक्स हाइलाइटिंग के लिए बड़े अक्षरों की आवश्यकता है):

  • कब suया sudo -iशामिल हैं:

    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
    
  • जब एक पृष्ठभूमि प्रक्रिया शुरू होती है:

    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
    

अब मैं अपने सिस्टम पर प्राप्त आउटपुट के बारे में हैरान हूँ systemd───xfce4-terminal───bash───pstree:। ऐसा क्यों है?
वैल

1
@val: systemd init प्रक्रिया है, अन्य सभी प्रक्रियाओं का जनक। आप स्पष्ट रूप से उपयोग कर रहे हैं xfce4-terminal, जिसने एक bashशेल लॉन्च किया, जिसके भीतर आप भागे pstree, जिसने स्वयं और उसके माता-पिता को सूचना दी। यदि आप सिस्टमड और xfce4- टर्मिनल के बीच के चरणों की कमी का मतलब है, तो यह हो सकता है कि जो कुछ भी xfce4- टर्मिनल लॉन्च किया गया है, उसकी मृत्यु हो गई हो या उसे अस्वीकार कर दिया गया हो, जिस स्थिति में यह init द्वारा विरासत में मिला होगा।
निक मैट्टेओ

पढ़ने का कोई कारण नहीं SHLVL? प्रक्रियाओं और प्रणालियों के दौरान पोर्टेबिलिटी, मुझे लगता है, लेकिन तब pstree स्थापित नहीं हो सकता है ..
D. बेन नोबल

नमस्कार, @ D.BenKnoble, जैसा कि @ egmont के उत्तर के तहत चर्चा की गई है , $SHLVLकुछ गोले द्वारा समर्थित नहीं है। अधिक विशिष्ट, ऊपर के डेमो से पर्यावरण के अनुसार यह केवल sh( dash) द्वारा समर्थित नहीं है - और इस चर को इस चर द्वारा बिल्कुल भी नहीं गिना जाता है। दूसरी ओर pstreeपैकेज psmisc का हिस्सा है जो कुछ भी प्रदान करता है fuser, killallऔर कुछ अन्य - यह उबंटू का मुख्य घटक है - मैंने इसे इस उत्तर में वर्णित सिस्टम पर स्थापित नहीं किया है।
पा ४० 30०

30

SHLVLशेल चर का मान जांचें :

echo $SHLVL

bashमैनुअल पेज से उद्धरण :

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

इसके द्वारा भी समर्थित है zsh


4
लेकिन sh की गिनती नहीं की जाती है, इसलिए दिए गए उदाहरण में, sh के साथ, SHLVL नहीं होगा। फिर भी, यह कुछ ऐसा है जो उन लोगों के लिए उपयोगी हो सकता है जो गोले को बहुत अधिक नहीं बदलते हैं
ubfan1

3
@ ubfan1 जब तक कोई ओवरराइडिंग vimrc परिभाषा नहीं है, :shउपयोगकर्ता के लॉगिन शेल में डिफॉल्ट करता है जो मुझे लगता है (यह वास्तव :shellमें एक विशिष्ट शेल बाइनरी के नाम के बजाय संक्षिप्त रूप है )
स्टीलड्राइवर

3
मैं विम के विवरण से परिचित नहीं हूं, लेकिन मैंने इस उत्तर को पोस्ट करने :shसे vimपहले कोशिश की है , और इसने मेरे लिए शेल स्तर में वृद्धि की है। मेरा लॉगिन शेल बैश है।
egmont

9

मेरे में .bashrc, मैं अपने वेरिएबल में " " संकेतों को जोड़कर $SHLVLसमायोजित करने का उपयोग करता हूं : $PS1+$SUBSHELL

...
# 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
...

फिर, मैं देख सकता हूँ कि मैं कितना गहरा हूँ:

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)$')

आप एक फ़ाइल में दो संस्करणों में से एक को रख सकते हैं और $ DEPTH को उपलब्ध करने के लिए स्रोत का उपयोग कर सकते हैं।

# 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

आप psपूरे शेल स्टैक (वर्तमान एक सहित) को देखने के लिए बिना किसी अतिरिक्त तर्क के उपयोग कर सकते हैं । यह उन सभी बैकग्राउंड जॉब्स को भी दिखा रहा होगा जो आपने psस्वयं शुरू की हैं , लेकिन यह आपको एक मोटा अनुमान दे सकता है कि आप कितने गहरे हैं।


यह ऊपर दिए { echo hello world; ps; } &गए psउत्तर को साबित करने के लिए काम करता है ।
WinEunuuchs2Unix

@ WinEunuuchs2Unix, मेरा मतलब कुछ इस तरह है: paste.ubuntu.com/p/6Kfg8TqR9V
pa4080

वहाँ एक रास्ता है pstree की नकल करने के लिए -s $ $ ps के साथ?
Bac0n
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.