exit
터미널을 종료하는 것을 방지하기 위해 내장 함수의 기능을 대체하는 함수를 작성하려고 합니다 .
환경 변수를 사용해 보았 SHLVL
으나 서브셸에서는 변경되지 않는 것 같습니다.
$ echo $SHLVL
1
$ ( echo $SHLVL )
1
$ bash -c 'echo $SHLVL'
2
내 기능은 다음과 같습니다.
exit () {
if [[ $SHLVL -eq 1 ]]; then
printf '%s\n' "Nice try!" >&2
else
command exit
fi
}
exit
하지만 이 방법으로 는 서브셸에서 사용할 수 없습니다 .
$ exit
Nice try!
$ (exit)
Nice try!
내가 서브셸에 있는지 감지할 수 있는 좋은 방법이 있습니까?
답변1
$BASHPID
Bash에서는 비교할 수 있습니다$$
$ ( 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
Bash를 사용하지 않는 경우 $$
하위 쉘에서 변경되지 않은 상태로 유지되어야 하므로 실제 프로세스 ID를 얻으려면 다른 방법이 필요합니다.
실제 pid를 얻는 한 가지 방법은 sh -c 'echo $PPID'
. 그냥 평범한 곳에 놔두면 ( … )
쉘이 이미 포크에 최적화되어 있어서 작동하지 않는 것처럼 보일 수도 있습니다. 추가 no-op 명령을 시도하여 ( : ; sh -c 'echo $PPID'; : )
서브셸이 최적화하기에는 너무 복잡하다고 생각하게 만드세요. 신용은 간다스택 오버플로의 John1024이 방법의 경우.
답변2
어때요 BASH_SUBSHELL
?
BASH_SUBSHELL 해당 환경에서
쉘이 실행을 시작할 때 각 서브쉘 또는 서브쉘 환경에 하나를 추가합니다.
초기값은 0입니다.
$ echo $BASH_SUBSHELL
0
$ (echo $BASH_SUBSHELL)
1
답변3
[댓글이어야 하는데 제가 쓴 댓글은 운영자에 의해 삭제되는 경향이 있어서 답변으로 남고, 삭제되더라도 참고용으로 사용할 수 있습니다.]
1로만 설정할 수 있으므로 사용하기에 BASH_SUBSHELL
완전히 신뢰할 수 없습니다.일부서브쉘이지만 모든 서브쉘에 있는 것은 아닙니다.
$ (echo $BASH_SUBSHELL)
1
$ echo $BASH_SUBSHELL | cat
0
파이프 명령을 실행하는 하위 프로세스가 파이프라인이 아님을 선언하는 경우진짜진정한 서브셸의 경우 다음 man bash
코드 조각을 고려하세요.
파이프라인의 각 명령은 별도의 프로세스(즉, 하위 셸에서)로 실행됩니다.
그리고 실질적인 의미 - 중요한 것은 용어상의 논쟁이 아니라 스크립트 조각이 하위 프로세스에서 실행되는지 여부입니다.
이 질문에 대한 답변에서 이미 설명했듯이 유일한 해결책은질문$BASHPID
이식성 과 동일 $$
하지만 훨씬 덜 효율적 인지 확인하는 것입니다 .
if [ "$(exec sh -c 'echo "$PPID"')" != "$$" ]; then
echo you\'re in a subshell
fi