Bir deniz kabuğu altında olup olmadığını nasıl anlayabilirim?


24

exitKendimi terminalden çıkmamak için yerleşikin işlevselliğini değiştiren bir işlev yazmaya çalışıyorum .

SHLVLOrtam değişkenini kullanmaya çalıştım, ancak alt kabuklarda değişmiyor gibi görünüyor:

$ echo $SHLVL
1
$ ( echo $SHLVL )
1
$ bash -c 'echo $SHLVL'
2

Benim işlevim aşağıdaki gibidir:

exit () {
    if [[ $SHLVL -eq 1 ]]; then
        printf '%s\n' "Nice try!" >&2
    else
        command exit
    fi
}

Bu exitolsa da alt kabuklarda kullanmama izin vermiyor :

$ exit
Nice try!
$ (exit)
Nice try!

Bir deniz kabuğu altında olup olmadığımı tespit etmek için iyi bir yöntem nedir?



1
Bu yüzden bu . Çünkü $ SHLVL 1'dir Eğer echo $ SHLVL komutu bir "alt kabukta" çalıştırmak olsa bile kabuk seviye 1 koruyor. Bu gönderiye göre, parantez içinde ortaya (...)çıkarılan alt kabuklar , ana sürecin tüm özelliklerini miras alır. Verilen cevaplar, kabuk seviyenizi belirlemek için daha sağlam çözümlerdir.
kemotep


5
@ mosvy Bunun farklı bir soru olduğunu hissediyorum. örneğin BASH_SUBSHELLcevap (tartışmalı olsa bile) bu soru için geçerli olmaz.
Sparhawk

2
HNQ unvanını gördüm ve bunun kuantum mekaniği meselesi olduğunu düşündüm ...
Mehrdad

Yanıtlar:


43

Bash, sen karşılaştırabilirsiniz $BASHPIDiçin$$

$ ( if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi )
subshell
$   if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi
not subshell

Eğer bash değilseniz $$, bir deniz kabuğu içinde aynı kalmalı, böylece gerçek işlem kimliğinizi almak için başka bir yola ihtiyacınız olacaktır.

Gerçek teklifinizi almanın bir yolu sh -c 'echo $PPID'. Bunu bir oraya koyarsanız, ( … )kabuğunuzun çatalı en iyi duruma getirdiği için işe yaramaz gibi görünebilir. ( : ; sh -c 'echo $PPID'; : )Alt kabuğun uzaklaşmak için fazla karmaşık olduğunu düşünmesini sağlamak için fazladan no-op komutları deneyin . Credit , bu yaklaşım için Stack Overflow'taki John1024'e gider .


Sen o değiştirmek isteyebilirsiniz  (sh -c 'echo $PPID'; : )bakınız - yorumumu üzerinde John1024 cevabı .
G-Man

@ G-Man Şey, bu sadece onu test etmek içindi (çünkü gerçek kullanımda daha karmaşık bir şey olurdu) ... ama evet, eğer test bütün kabuklarda çalışsa en iyisi olurdu. Ben de önce ve sonra bir no-op koymak, bu umarım her şeyi halleder.
derobert

38

Ne dersiniz BASH_SUBSHELL?

BASH_SUBSHELL
      Kabuk
      o ortamda çalışmaya başladığında , her alt kabuk veya alt kabuk ortamında birer birer artar . İlk değer 0'dır.

$ echo $BASH_SUBSHELL
0
$ (echo $BASH_SUBSHELL)
1

16
Inception filminde uygun bir komut olurdu.
Eric Duminil

Başlangıçta muhtemelen $ SHLVL
Büyükanne Aching

19

[bu bir yorum olmalıydı, ancak yorumlarım moderatörler tarafından silinme eğilimindeydi, bu yüzden silinmiş olsa bile referans olarak kullanabileceğim bir cevap olarak kalacağım]

Kullanılması BASH_SUBSHELLsadece 1 olarak ayarlanmalıdır olarak tamamen güvenilmez bazı tüm altkabuklarda içinde, altkabuklarda.

$ (echo $BASH_SUBSHELL)
1
$ echo $BASH_SUBSHELL | cat
0

Bir boru hattı komut çalıştırıldığında altişlem bir olmadığını iddia Önce gerçekten gerçek altkabuk, bunu dikkate man bashpasajı:

Bir boru hattındaki her komut ayrı bir işlem olarak yürütülür (yani, bir alt kabukta).

ve pratik çıkarımlar - bir senaryo parçasının bir alt işlemi çalıştırıp çalıştırmadığı veya bazı terminoloji tartışmaları için zorunlu olmayan bir işlem olup olmadığı.

Bu sorunun cevaplarında daha önce de açıklandığı gibi tek çözüm, $BASHPIDeşit mi yoksa $$taşınabilir olarak mı , yoksa çok daha az verimli mi olduğunu kontrol etmektir :

if [ "$(exec sh -c 'echo "$PPID"')" != "$$" ]; then
    echo you\'re in a subshell
fi

11
Nit: BASH_SUBSHELLoldukça güvenilir bir şekilde ayarlanmış, ancak değerini doğru bir şekilde almak çok zordur. Dokümanların söylediklerini not edin : " Kabuk, bu ortamda çalışmaya başladığında her bir alt kabuk veya alt kabuk ortamında birer birer artar. " Sen karşılaştırabilirsiniz echo $BASH_VERSIONile declare -p BASH_VERSION- ikinci gerektiği güvenilir vb borular, arka plan işleri ile çıkış 1
Muru

6
Yine de, eval 'echo $BASH_SUBSHELL $BASHPID' | cat1 için çıktı olacaktır BASH_SUBSHELL, çünkü değişken çalıştırma başladıktan sonra genişler.
muru,

4
Tüm bu argümanlar aynı zamanda ikame, komut işlemleri, bg işlemleri için de geçerli olmalıdır, ancak bu sadece farklı olan boru hatlarıdır. Kurallara bakıldığında, artma , muhtemelen bazı nedenleri olan, ancak bunu yapamadığım ; ön plan boru hatları için subshell_levelgerçekten ertelenmiştir ;-)
mosvy

2
Haklısın. Görünüşe göre Chet açıkça böyle düşünüyor. lists.gnu.org/archive/html/bug-bash/2015-06/msg00050.html : "BASH_SUBSHELL ölçüleri (...) alt kabuklar, boru hattı elemanları değil." lists.gnu.org/archive/html/bug-bash/2015-06/msg00054.html : "Statükoyu belgelemek mi yoksa $ BASH_SUBSHELL'in yansıtan" subshell "tanımını genişletip genişletmemem gerektiğini düşüneceğim. "
muru

2
@JoL yanılıyorsunuz, genişleme de ayrı bir süreçte gerçekleşiyor, lütfen yukarıdaki tartışma ve bağlantıları okuyun; ya da sadece deneyin echo $$ $BASHPID $BASH_SUBSHELL | cat.
mosvy 19
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.