질문: 내가 가지고 있는 껍질이 몇 개인지 알아보세요.
세부 사항: 나는 종종 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; 명령 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
지원되는 shell 을 사용하기 시작하면 혼란을 야기할 수 있으므로 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
다음 두 줄에 추가하십시오(또는 현재 PS1
값을 변경하십시오).
PS1="${SHLVL} \w\$ "
export PS1
결과:
1 ~$ bash
2 ~$ bash
3 ~$ exit
exit
2 ~$ exit
exit
1 ~$
프롬프트 문자열 시작 부분의 숫자는 쉘 레벨을 나타냅니다.
두 번째 변형에는 중첩된 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 - 쉘 깊이 수준