Masalah : Temukan berapa banyak kerang dalam diriku.
Detail : Saya sering membuka shell dari vim. Bangun dan jalankan dan keluar. Kadang-kadang saya lupa dan membuka vim lain di dalam dan kemudian shell lain. :(
Saya ingin tahu berapa banyak kerang dalam diri saya, mungkin bahkan ada di layar shell saya setiap saat. (Saya dapat mengatur bagian itu).
Solusi saya : Parsing pohon proses dan cari vim dan bash / zsh dan cari tahu kedalaman proses saat ini di dalamnya.
Apakah sesuatu seperti itu sudah ada? Saya tidak dapat menemukan apa pun.
$SHLVL
variabel (dikelola oleh beberapa shell) apa yang Anda cari?fg
untuk kembali, yang tidak memiliki masalah ini.vim
pekerjaan paralel yang terhenti mungkin lebih membingungkan daripada memiliki setumpuk proses bersarang. Oleh karena itu, saya lebih suka memiliki beberapa jendela , jadi saya dapat dengan mudah melompat-lompat dengan cepat, tetapi saya tidak akan menyebut ini masalah XY hanya karena saya lebih suka alur kerja yang berbeda.Jawaban:
Ketika saya membaca pertanyaan Anda, pikiran pertama saya adalah
$SHLVL
. Lalu saya melihat bahwa Anda ingin menghitungvim
level selain level shell. Cara sederhana untuk melakukan ini adalah dengan mendefinisikan fungsi shell:Ini akan secara otomatis dan diam-diam bertambah
SHLVL
setiap kali Anda mengetikvim
perintah. Anda perlu melakukan ini untuk setiap varianvi
/vim
yang pernah Anda gunakan; misalnya,Set kurung luar membuat subkulit, sehingga perubahan manual dalam nilai
SHLVL
tidak mencemari lingkungan shell (induk) saat ini. Tentu sajacommand
kata kunci itu ada untuk mencegah fungsi memanggil diri mereka sendiri (yang akan menghasilkan loop rekursi tak terbatas). Dan tentu saja Anda harus meletakkan definisi ini ke dalam.bashrc
file inisialisasi shell Anda atau lainnya.Ada sedikit inefisiensi di atas. Dalam beberapa shell (bash menjadi satu), jika Anda mengatakannya
di mana ada program eksternal yang dapat dieksekusi (yaitu, bukan perintah bawaan), shell menyimpan proses tambahan di sekitar, hanya untuk menunggu untuk mengakhiri. Ini (bisa dibilang) tidak perlu; kelebihan dan kekurangannya masih bisa diperdebatkan. Jika Anda tidak keberatan mengikat sedikit memori dan slot proses (dan untuk melihat satu proses shell lebih dari yang Anda butuhkan saat melakukan a ), maka lakukan hal di atas dan lewati ke bagian berikutnya. Ditto jika Anda menggunakan shell yang tidak membuat proses ekstra berbaring. Tetapi, jika Anda ingin menghindari proses ekstra, hal pertama yang harus dicoba adalah
cmdn
cmdn
ps
The
exec
perintah yang ada untuk mencegah proses shell ekstra dari berlama-lama.Tapi, ada gotcha. Penanganan shell
SHLVL
agak intuitif: Ketika shell mulai, ia memeriksa apakahSHLVL
sudah diatur. Jika tidak disetel (atau disetel ke selain angka), shell menetapkannya ke 1. Jika disetel (ke angka), shell menambahkan 1 ke dalamnya.Tetapi, dengan logika ini, jika Anda berkata
exec sh
, AndaSHLVL
harus naik. Tapi itu tidak diinginkan, karena level shell asli Anda belum meningkat. Shell menangani ini dengan mengurangi satu dariSHLVL
saat Anda melakukanexec
:Begitu
adalah mencuci; itu akan menambahkan
SHLVL
hanya untuk pengurangan lagi. Anda mungkin juga hanya mengatakanvim
, tanpa manfaat dari suatu fungsi.Untuk memperbaikinya, Anda harus melakukannya
Lalu saya melihat bahwa Anda ingin menghitung
vim
level secara terpisah dari level shell. Nah, trik yang sama persis berfungsi (well, dengan sedikit modifikasi):(dan seterusnya untuk
vi
,,view
dll.)export
Diperlukan karenaVILVL
tidak didefinisikan sebagai variabel lingkungan secara default. Tetapi tidak harus menjadi bagian dari fungsi; Anda bisa mengatakanexport VILVL
sebagai perintah terpisah (di Anda.bashrc
). Dan, seperti yang dibahas di atas, jika proses shell tambahan tidak menjadi masalah bagi Anda, Anda dapat melakukancommand vim
alih - alihexec vim
, dan biarkanSHLVL
sendiri:Jika Anda menggunakan shell yang tidak mendukung
SHLVL
(mis., Dash), Anda bisa mengimplementasikannya sendiri selama shell mengimplementasikan file startup. Lakukan saja sesuatu sepertidalam
.profile
file Anda atau yang berlaku. (Anda mungkin tidak boleh menggunakan namaSHLVL
, karena itu akan menyebabkan kekacauan jika Anda mulai menggunakan shell yang mendukungSHLVL
.)Jawaban lain telah membahas masalah menanamkan nilai variabel lingkungan ke prompt shell Anda, jadi saya tidak akan mengulanginya, terutama Anda mengatakan Anda sudah tahu bagaimana melakukannya.
sumber
ps
ataupstree
, ketika Anda dapat melakukan ini dengan shell builtins.dash
memiliki ekspansi aritmatika.SHELL_LEVEL=$((SHELL_LEVEL + 1))
seharusnya cukup walaupun $ SHELL_LEVEL sebelumnya tidak disetel atau kosong. Ini hanya jika Anda harus portabel untuk shell Bourne yang Anda akan perlu untuk menggunakanexpr
, tapi kemudian Anda juga akan perlu mengganti$(...)
dengan`..`
.SHELL_LEVEL=`expr "${SHELL_LEVEL:-0}" + 1`
bash
script untuk membaca ~ / .bashrc oleh membuat stdin soket misalnya), maka itu bisa menjadi masalah. Itu banyak "jika", tetapi sesuatu yang harus diingat seseorang (data yang tidak bersih dalam konteks aritmatika berbahaya)Anda bisa menghitung sebanyak waktu yang Anda butuhkan untuk naik pohon proses sampai Anda menemukan pemimpin sesi. Suka dengan
zsh
di Linux:Atau POSIXly (tetapi kurang efisien):
Itu akan memberi 0 untuk shell yang dimulai oleh emulator terminal Anda atau getty dan satu lagi untuk setiap keturunan.
Anda hanya perlu melakukannya sekali saat startup. Misalnya dengan:
di
~/.zshrc
atau setara dengan memilikinya di prompt Anda.tcsh
dan beberapa kerang lainnya (zsh
,ksh93
,fish
danbash
setidaknya) mempertahankan$SHLVL
variabel yang mereka kenaikan pada startup (dan penurunan sebelum menjalankan perintah lain denganexec
(kecuali yangexec
ada di subkulit jika mereka tidak kereta (tapi banyak yang))). Itu hanya melacak jumlah shell nesting, bukan proses nesting. Level 0 juga tidak dijamin menjadi pemimpin sesi.sumber
Gunakan
echo $SHLVL
. Gunakan prinsip KISS . Tergantung pada kompleksitas program Anda, ini mungkin cukup.sumber
bash
, tetapi tidak untukdash
.Salah satu solusi potensial adalah dengan melihat output dari
pstree
. Ketika dijalankan di dalam cangkang yang muncul dari dalamvi
, bagian dari pohon pohon yang ada di daftarpstree
harus menunjukkan seberapa dalam diri Anda. Sebagai contoh:sumber
Varian pertama - kedalaman shell saja.
Solusi sederhana untuk
bash
: tambahkan ke.bashrc
dua baris berikutnya (atau ubahPS1
nilai Anda saat ini ):Hasil:
Nomor di awal string cepat akan menunjukkan level shell.
Varian kedua, dengan vim bersarang dan level shell keduanya.
tambahkan baris ini ke
.bashrc
Hasil:
v: 1 - vim level kedalaman
s: 3 - level kedalaman shell
sumber
Dalam pertanyaan yang Anda sebutkan parsing
pstree
. Ini cara yang relatif sederhana:The
pstree
pilihan:-A
- Output ASCII untuk memudahkan penyaringan (dalam kasus kami setiap perintah didahului oleh`-
)-a
- tampilkan juga perintah argumen, sebagai efek samping setiap perintah ditampilkan pada baris terpisah dan kita dapat dengan mudah memfilter output menggunakangrep
-l
- jangan memotong garis panjang-s
- perlihatkan orang tua dari proses yang dipilih(sayangnya tidak didukung di versi lama
pstree
)$$
- proses yang dipilih - PID dari shell saat inisumber
Ini tidak sepenuhnya menjawab pertanyaan tetapi dalam banyak kasus mungkin membuatnya tidak perlu untuk melakukannya:
Saat pertama kali meluncurkan shell Anda, jalankan
set -o ignoreeof
. Jangan memasukkannya ke dalam~/.bashrc
.Biasakan untuk mengetikkan Ctrl-D ketika Anda berpikir Anda berada di shell tingkat atas dan ingin memastikan.
Jika Anda tidak berada di shell tingkat atas, Ctrl-D akan memberi sinyal "end of input" ke shell saat ini dan Anda akan mundur satu tingkat.
Jika Anda berada di shell tingkat atas, Anda akan mendapatkan pesan:
Saya menggunakan ini sepanjang waktu untuk sesi SSH dirantai, untuk membuatnya mudah untuk kembali ke tingkat tertentu dari rantai SSH. Ia bekerja untuk cangkang bersarang juga.
sumber