현재 쉘 인터프리터 이름을 *안정적으로* 그리고 *쉽게* 얻으려면 어떻게 해야 합니까?

현재 쉘 인터프리터 이름을 *안정적으로* 그리고 *쉽게* 얻으려면 어떻게 해야 합니까?

저는 스크립트나 소스 파일에서 현재 셸의 이름을 가져오는 간단하고 안정적인 방법을 찾고 있습니다(아니요명령줄에서). 나는 이것을 하고 싶었지만 $(basename "$SHELL")내 로그인 쉘이 있고 zshsome_script.sh에 다음 코드가 있는 경우

this_shell=$( basename "$SHELL" )
echo "The Shell is $this_shell"
echo "The Shell is $0"

로 실행했는데 사용된 인터프리터가 이었음에도 불구하고 bash some_script.sh여전히 나열되었습니다 . 쉘 디자이너가 왜 현재 쉘 대신 기본 쉘을 표시하기로 선택했는지는 잘 모르겠지만, 그것이 우리가 고수하고 있는 것 같습니다.zshbash/bin/bash

다른 약간 유사한 질문이 있습니다(여기그리고여기), 그러나 그들의 답변은 여러 면에서 부족합니다.

  1. 그들은 종종 사용자가 현재 어떤 대화형 셸을 사용하고 있는지 알아내려고 한다고 가정하지만 이는 말도 안되는 일입니다. 어떤 쉘에 명령을 입력할지 알고 있습니다. 어떤 쉘을 결정하려면 어디에서나 실행할 수 있는 코드가 필요합니다.그것사용하고 있습니다.
  2. 그들은 종종 몇 가지 다른 시도를 제공합니다. 명령줄에서 하듯이 bash를 사용하고 있다는 것을 알 때까지 만지작거리지만 저는 모든 상황에서 신뢰할 수 있는 한 가지가 필요했습니다.
  3. 그들은 종종 스크립트에서 완전히 쓸모없는 것들을 제공합니다 echo $0. 예를 들어 위의 스크립트에서 볼 수 있듯이 실패합니다. (예, 대화형 쉘 명령줄에서 작동합니다. 그런데 어떤 쉘을 사용하고 있는지 모르는 이유는 무엇입니까?)
  4. 그들은 때때로 명령을 내립니다(제한된 테스트에서).포함하다와 같은 정보는 정확 ps -p $$하지만 파이프를 통과하기 위한 크로스 플랫폼, 크로스 쉘 호환 sed/awk 명령이 부족합니다.그냥 쉘 이름함께 제공되는 다른 메시지는 무시하세요.
  5. $BASH_VERSION여기에는 및 와 같은 몇 가지 셸에서만 실행되는 항목이 포함됩니다 $ZSH_VERSION. fish,,, 등 가능한 한 많은 쉘을 지원하고 싶습니다 csh.tcsh

내가 어떻게 할안정적으로그리고정밀한발각어느 현재의껍데기? 저는 플랫폼, 스크립트 및 가능한 한 많은 합리적인 쉘 에서 작동하는 것을 찾고 있습니다 1.

고쳐 쓰다: 이 질문을 게시했을 때 이 정보를 제공하기 위해 쉘에 일부 기능이 내장되어 있을 것으로 예상했지만 그렇지 않은 것 같습니다. 이제는 뭔가에 의지하는 게 불가피해 보이니까밖의Shells, 내가 원하는 것은 더 구체적으로 말했어야 했는데크로스 플랫폼해결책 (위의 다른 답변에 대한 내 반대 투표는 이에 대한 힌트를 주지만 질문을 주의 깊게 읽지 않으면 놓치기 쉬울 수 있습니다).

업데이트 2 Stéphane의 답변은 Linux 전용이 아니기 때문에 이것이 Linux 전용 질문과 중복된다고 생각하는 사람이 있다면 여기에 제가 요청한 것과 그가 제공한 것의 차이점이 있습니다. (그는 그것을 매우 영리하게 썼고 나는 그것을 두드리지 않지만 그것이 내 문제를 해결하지는 않는다는 점에 유의하십시오.)

  1. 나는 뭔가를 찾고 있어요단순한그리고믿을 수 있는, 저것
  2. .zshrc모든 스크립트 또는 함수 정의( 또는 .bash_profile다른 소스 에 의해 분기됨)에 추가될 수 있습니다 .
  3. 그의 스크립트는 항상 기본 인터프리터에 의해 해석되고 반환되므로 인터프리터 이름을 호출 스크립트/함수에 전달하는 외부 유틸리티로 사용할 수 없습니다. 이로 인해 내 목적으로 사용하기가 어렵거나 불가능해집니다. 가능하다면 여전히 매우 어렵고 이를 작동시키는 솔루션은 다음과 같습니다.아니요답변에 주어졌습니다. 그래서 그는 내 질문에 대답하지 않았으므로 중복이 아닙니다.

뭔가 보고 싶다면~ 할 것이다일하고 봐GitHub의 ShellDetective. 이렇게 하면 이미 SE에 있는 것과 이 질문이 찾고 있는 것(실제로 다른 곳에서는 충족되지 않은 이 질문에 대한 요구를 충족시키기 위해 작성된 것) 간의 차이점을 더 쉽게 확인할 수 있습니다.


(PS, 그러한 사용 사례가 있다고 생각하지 않는다면, 사용 중인 서버와 사용 가능한 쉘에 따라 .zshrc, .bash_profile, 또는 로 소스되는 기능을 상상해 보십시오 .profile. 해당 기능은 소스이므로 shebang이 없습니다. 어떤 쉘에서든 작동하면 가장 유용하지만 때로는 실행 방법을 알기 위해 어떤 쉘에 있는지 알아야 합니다.


1 나는 전통적인 의미에서 껍질이 아닌 "껍질"에 관심이 없습니다. 나는 누군가가 스스로 작성한 쉘에는 관심이 없습니다. 난 단지 관심진짜 껍질이것은 실제로 실제로 발생하며 누군가가 일부 서버에 로그인할 때 이것을 사용해야 할 수도 있고 원하는 쉘을 설치할 수 없을 수도 있습니다.

답변1

이 조합으로 좋은 결과를 얻었습니다.

ps -p $$ | awk '$1 != "PID" {print $(NF)}'

Tru64(OSF/1)에서는 출력의 셸 주위에 괄호가 있습니다. tr -d '()'제거할 접착제입니다 .

ps -p $$ | awk '$1 != "PID" {print $(NF)}' | tr -d '()'  

모든 쉘, Solaris 10 및 RHEL 5.7/6.4에서 작동하는 것 같습니다. Debian, Ubuntu 또는 Mint와 같은 다른 배포판은 테스트하지 않았지만 모두 동일하게 작동해야 한다고 가정합니다. FreeBSD도 작동할지 모르겠습니다.

여기에 이미지 설명을 입력하세요.

답변2

그래서 나는 아직도 이것을 구체화하려고 노력하고 있지만 효과적인 아이디어가 있다고 생각합니다. 이미 알고 있듯이, 모든 쉘에서 수행하려는 작업은 불가능하지는 않더라도 매우 어렵습니다(폴리글롯에 추가하는 모든 변형은 선형 속도보다 더 큰 속도로 복잡성을 증가시킵니다). Bourne(sh, ash, dash, bash, ksh, pdksh, zsh 등)과 C 스타일 셸(csh, tcsh, fish 등)로 분할하면 아마도 그렇게 할 수 있지만 csh현재 변형 간의 변경 사항이 있습니다 . 다양하고 흥미로운 변화의 도전.

따라서 알려진 언어(bash, C, perl, python 등 shebang 라인 포함)로 탐지 루틴을 작성하고 상위 실행 파일의 이름을 결정해 보겠습니다. 그런 다음 두 가지 트릭을 사용하여 정보를 부모에게 반환할 수 있습니다. 즉, 반환 값과 표준 출력에 기록되는 단일 단어입니다. sh가 삭제된 쉘에서는 0을 반환하고 쉘 이름을 쓸 것입니다. 왜냐하면 모두 백틱 처리가 잘 되기 때문입니다. C 시리즈 셸에서는 해결해야 하는 각 비호환성 세트에 대한 반환 값을 추가하기 시작할 수 있습니다. 200을 초과하는 반환 값은 오류를 나타내며 처음에는 모든 것이 괜찮아 보이지만 200에서는 부모님이 누구인지 알 수 없습니다.

내부 절차는 Linux에서 간단해 보입니다( /proc/ppid/exe전투의 절반이 승리합니다). ps 옵션을 사용하여 bsd에서 이 작업을 수행할 수 있다고 확신하지만 현재 테스트할 실행 중인 bsd 시스템이 없으며 내 Mac에는 새 하드 드라이브(어쨌든 10.4만)가 필요합니다. 셸 구문 문제를 크게 줄여주기는 하지만 다른 호환성 문제가 발생합니다. 나는 아직도 가능성이 있다고 생각한다.

답변3

이런 것을 시도해 보세요

shell_bin=$(ps h -p $$ -o args='' | cut -f1 -d' ')
echo $shell_bin

답변4

이건 어때요, 죄송합니다. 시도해 볼 플랫폼이 많지 않습니다.

local __shell=`ps $$ -o comm=""`

관련 정보