質問:私が持っている殻が何個あるのか調べてください。
詳細:私はしばしばvimでシェルを開きます。ビルドして実行して終了します。時には別のvimを開いて別のシェルを開くのを忘れることがあります。 :(
私のシェルがどれほど深いか知りたいです。たぶん私のシェル画面に深く入るかもしれません。 (その部分は私が管理できる。)
私のソリューション:プロセスツリーを解析し、vimとbash / zshを見つけて、現在のプロセスがどれほど深いかを調べます。
似たようなものはすでに存在していますか?何も見つかりません。
答え1
あなたの質問を読んだときに最初に考えたことはありました$SHLVL
。それからvim
レベルを計算したいのを見ました。またシェルレベル。簡単な方法はシェル関数を定義することです。
vim() { ( ((SHLVL++)); command vim "$@");}
SHLVL
コマンドを入力するたびに、値は自動的に自動的に増加しますvim
。たとえば、/を使用したvi
すべてのバリアントに対してこれを行う必要があります。vim
vi() { ( ((SHLVL++)); command vi "$@");}
view() { ( ((SHLVL++)); command view "$@");}
外側の括弧グループはサブシェルを作成するため、値を手動で変更してもSHLVL
現在の(親)シェル環境は汚染されません。もちろん、command
キーワードの目的は、関数が自分自身を呼び出すのを防ぐことです(これにより無限再帰ループが発生します)。もちろん、これらの定義を自分.bashrc
または他のシェル初期化ファイルに入れる必要があります。
上記は少し非効率的です。一部のシェルでは(bashがそのうちの1つです)、
(コマンド1; コマンド2;…; コマンドn)
外部実行プログラムの場合(つまり、組み込みコマンドではない)、シェルは終了を待つ追加のプロセスを維持します。これは(おそらく)不要です。長所と短所は議論の余地があります。少しのメモリとプロセススロットを占有しても大丈夫であれば(そしてそのタスクを実行するときに必要以上のシェルプロセスが表示される場合)、上記のタスクを実行して次のセクションに進んでください。追加のプロセスを維持しないシェルを使用する場合は、上記と同じです。しかし、追加のプロセスを避けたい場合は、最初に試してみてくださいcmdn
cmdn
ps
vim() { ( ((SHLVL++)); exec vim "$@");}
このexec
コマンドの目的は、追加のシェルプロセスが移動するのを防ぐことです。
しかし、問題があります。シェルの処理はやや直感的です。シェルが起動したら設定されていることをSHLVL
確認してください。SHLVL
設定されていない場合(または数値以外の値に設定されている場合)、シェルはこれを1に設定します。設定すると(数値で設定)、シェルはそれを1ずつ増やします。
だがその論理によれば'といえば上がらなければならないexec sh
。SHLVL
実際のシェルレベルは増加しないので、これはお勧めできません。シェルはこの問題を次のように処理します。マイナス1~から SHLVL
以下を行うときexec
:
$ echo "$SHLVL"
1
$ set | grep SHLVL
SHLVL=1
$ env | grep SHLVL
SHLVL=1
$ (env | grep SHLVL)
SHLVL=1
$ (env) | grep SHLVL
SHLVL=1
$ (exec env) | grep SHLVL
SHLVL=0
だから
vim() { ( ((SHLVL++)); exec vim "$@");}
それは洗濯です。SHLVL
再び減少するためだけに増加します。vim
機能の利点がなくても、そう言うこともできます。
メモ:
すべてを知っているStéphane Chazelasによると、いくつかの殻は十分にスマートです。いいえexec
サブシェルにいる場合は、これを行います。
この問題を解決するには、次の手順を実行します。
vim() { ( ((SHLVL+=2)); exec vim "$@");}
vim
それからレベルを計算したいのを見ました。独立シェルレベル。まあ、同じトリックが動作します(少しだけ修正してください)。
vim() { ( ((SHLVL++, VILVL++)); export VILVL; exec vim "$@");}
vi
(forなどview
)はデフォルトでは環境変数として定義されていないため、export
必須です。しかし、関数の一部である必要はありません。別のコマンドでVILVL
話すことができます(あなたのコマンドで)。そして、上記のように追加のシェルプロセスが問題にならない場合は、次のことを実行できます。export VILVL
.bashrc
command vim
exec vim
SHLVL
vim() { ( ((VILVL++)); command vim "$@");}
個人的な好み:
VILVL
同様の名前に変更することもできますVIM_LEVEL
。 「」を見るとVILVL
目が痛いです。 「vinyl」のスペルが間違っているのか、ローマ数字の間違いなのかはわかりませんでした。
使用しているシェルがそれをサポートしていない場合SHLVL
(ダッシュなど)、シェルが起動ファイルを実装している限り、直接実装できます。ただ次のようにしてください
if [ "$SHELL_LEVEL" = "" ]
then
SHELL_LEVEL=1
else
SHELL_LEVEL=$(expr "$SHELL_LEVEL" + 1)
fi
export SHELL_LEVEL
あなた.profile
またはそのファイルに。 (SHLVL
サポートされているシェルを使用し始めると混乱を招く可能性があるため、namesを使用しないでくださいSHLVL
。)
他の回答では、すでに環境変数の値をシェルプロンプトに含めるという問題に対処しているので、特にこれを行う方法を既に知っていると述べたので繰り返しません。
答え2
セッションリーダーが見つかるまでプロセスツリーを検索するのにかかる回数を数えることができます。zsh
Linuxと同様に:
lvl() {
local n=0 pid=$$ buf
until
IFS= read -rd '' buf < /proc/$pid/stat
set -- ${(s: :)buf##*\)}
((pid == $4))
do
((n++))
pid=$2
done
echo $n
}
またはPOSIXly(しかしそれほど効率的ではありません):
lvl() (
unset IFS
pid=$$ n=0
until
set -- $(ps -o ppid= -o sid= -p "$pid")
[ "$pid" -eq "$2" ]
do
n=$((n + 1)) pid=$1
done
echo "$n"
)
これは、ターミナルエミュレータまたはgettyによって開始されたシェルに対して0を提供し、各サブアイテムに対して1を提供します。
起動時に一度だけ実行できます。たとえば、
PS1="[$(lvl)]$PS1"
あなたまたはそれに対応するコンテンツの~/.zshrc
プロンプトにそれを含めます。
tcsh
そして、他のいくつかのシェル(zsh
、、、少なくとも)は起動時に増加ksh93
する変数を保持します(そして他のコマンドを実行する前に減少します(サブシェルにエラーがない場合(しかし多くの場合エラーが発生した場合)は除く)) 。数量のみを追跡します。fish
bash
$SHLVL
exec
exec
シェルただし、入れ子になったプロセスではなく、入れ子になったプロセスです。また、レベル0がセッションリーダーになることもできません。
答え3
使用echo $SHLVL
。使用キスの原理。プログラムの複雑さによっては、これで十分かもしれません。
答え4
最初の変形 - シェルの深さのみ。
簡単な解決策bash
:.bashrc
次の2行に追加します(または現在のPS1
値を変更します)。
PS1="${SHLVL} \w\$ "
export PS1
結果:
1 ~$ bash
2 ~$ bash
3 ~$ exit
exit
2 ~$ exit
exit
1 ~$
プロンプト文字列の先頭の数字はシェルレベルを表します。
2番目のバリエーションには、入れ子になったvimレベルとシェルレベルの両方があります。
この行を次に追加します。.bashrc
branch=$(pstree -ls $$)
vim_lvl=$(grep -o vim <<< "$branch" | wc -l)
sh_lvl=$(grep -o bash <<< "$branch" | wc -l)
PS1="v:${vim_lvl};s:$((sh_lvl - 1)):\w\$ "
export PS1
結果:
v:0;s:1:/etc$ bash
v:0;s:2:/etc$ bash
v:0;s:3:/etc$ vim
##### do ':sh' command in the vim, shell level is increasing by 1
v:1;s:4:/etc$ vim
##### do ':sh' command in the vim, shell level is increasing by 1
v:2;s:5:/etc$ bash
v:2;s:6:/etc$
v:1 - vim 深さレベル
s:3 - シェル深さレベル