현재 쉘을 판별하는 checkbashisms 호환 방법


18

내에서는 .profile로그인 쉘이 실제로 Bash 인 경우 Bash 관련 별칭 및 함수가 소스인지 확인하기 위해 다음 코드를 사용합니다 .

# If the current (login) shell is Bash, then
if [ "${BASH_VERSION:-}" ]; then
  # source ~/.bashrc if it exists.
  if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
  fi
fi

현재 쉘 구성 파일, 스크립트 및 기능을 버전 제어하에 두는 중입니다. 또한 최근에 교체, 예를 들어, Bash 전용의 기능을 활용할 수없는 쉘 스크립트에서 캐주얼 Bashisms을 제거하는 과정을 시작했습니다 function funcname()과를 funcname().

쉘 파일 저장소의 경우 저장소 의 각 파일 에서 Debian의 devscripts 패키지 에서 유틸리티 를 실행하는 커밋 사전 후크를 구성하여 실수로 Bash 특정 구문을 도입하지 않도록했습니다. 그러나 이것은 내 오류가 발생합니다 .checkbashismssh.profile

possible bashism in .profile line 51 ($BASH_SOMETHING):
if [ "${BASH_VERSION:-}" ]; then

에 어떤 경고 메시지가 표시되지 않는지를 확인하는 방법이 있는지 궁금합니다 checkbashisms.

나는 목록을 확인 POSIX으로 나열 쉘 관련 변수 중 하나가 현재 쉘을 표시하는 데 사용 수 있다는 희망을. 또한 대화식 Dash 셸에서 설정된 변수를 살펴 보았지만 다시 한 번 적합한 후보를 찾지 못했습니다.

현재로서는에 .profile의해 처리되는 것을 제외 했습니다 checkbashisms. 작은 파일이므로 수동으로 확인하기가 어렵지 않습니다. 그러나이 문제를 연구 한 결과 POSIX 호환 방법이 어떤 쉘이 실행 중인지 (또는 적어도 checkbashisms실패 하지 않는 방법) 확인하는 방법을 알고 싶습니다 .


추가 배경 / 설명

쉘 구성 파일을 버전 제어로 설정하는 이유 중 하나는 현재 정기적으로 로그인하는 모든 시스템에서 환경을 구성하는 것입니다. Cygwin, Ubuntu 및 CentOS (5 및 7 모두 사용자 용 Active Directory 사용) 입증). X Windows / 데스크톱 환경과 원격 호스트의 SSH를 통해 가장 자주 로그온합니다. 그러나 나는 이것이 미래의 증거이며 가능한 한 시스템 종속성 및 기타 도구에 가장 의존하지 않기를 바랍니다.

내가 사용하고 checkbashisms내 껍질 관련 파일의 구문에 대한 간단한 자동화 전성 검사한다. 그것은 완벽한 도구가 아닙니다. 예를 들어, command -v스크립트에 사용하는 것에 대해 불평하지 않도록 패치를 이미 적용했습니다 . 조사하는 동안 프로그램의 실제 목적은 2008 년 (또는 2013 년 개정판)이 아닌 POSIX 2004를 기반으로하는 데비안 정책을 준수하는 것임을 알게되었습니다.


요점은 POSIX 호환 환경에서 요점을 다르게 실행해야 할 때 POSIX 호환입니다. 당신의 쇠고기는 체크 버시가 있습니다.
Gilles 'SO- 악마 그만해'

그런데 checkbashisms를 사용하여 구성의 이식성을 확인한 적이 없습니다. 다른 시스템에서 사용하여 확인합니다.
Gilles 'SO- 악마 그만

2
.bash_profile그건 그렇고, 여기서 당신이하고있는 특정 일에 대해 .profile(조건부) 소스를 작성하십시오 .bashrc.
Gilles 'SO- 악마 그만

의견 @Gilles에 감사드립니다. 특정 문제에 대한 매우 우아한 솔루션입니다.
Anthony G-0

답변:


16

너의

# If the current (login) shell is Bash, then
if [ "${BASH_VERSION:-}" ]; then
  # source ~/.bashrc if it exists.
  if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
  fi
fi

코드는 POSIX를 준수하며 현재 실행 중인지 확인하는 가장 좋은 방법 bash입니다. 물론 $BASH_VERSION변수는 bash 전용이지만 특히 사용하는 이유입니다! 실행 중인지 확인하려면 bash!

참고 $BASH_VERSION여부를 설정 될 것이다 bash으로 호출 bash하거나 sh. 실행 중이라고 주장 하면 셸이 호출되었다는 표시기로 bash사용할 수 있습니다 (이 옵션은 POSIXLY_CORRECT가 환경에 있거나 환경에서 으로 호출 되거나 SHELLOPTS = posix로 호출 될 때도 설정 됨) . 그러나 모든 경우에 마치 ) 처럼 호출됩니다 .[ -o posix ]shbash-o posixbashsh


또 다른 변수는 당신이 대신 사용할 수 $BASH_VERSION와 그 checkbashism전달하지 않는 한에 대해 불평하지 않는 것 -x옵션입니다 $BASH. 그것은 또한 bash당신에게 달려 있는지 여부를 결정하는 데 사용할 수 있어야 하기 때문에 특정합니다 bash.


또한 실제로 제대로 사용되지 않는다고 주장합니다 checkbashisms. POSIX의 상위 세트 인 데비안 정책 의 사양에 따라 checkbashisms이식 가능한 sh스크립트 를 작성하는 데 도움이되는 도구로 sh, sh심볼릭 링크가있는 시스템에서 스크립트를 작성하는 사람들이 도입 한 비표준 구문을 식별하는 데 도움 이됩니다 bash.

A .profile는 다른 쉘에 의해 해석되며, 대부분은 POSIX를 준수하지 않습니다. 일반적으로 sh로그인 쉘로 사용하지 않지만 zsh, fish또는 bash고급 대화식 기능과 같은 쉘을 사용 합니다.

bash그리고 zsh, sh각각의 프로파일 세션 파일 ( .bash_profile, .zprofile)이 호출되지 않았을 때 POSIX 호환 (특히 zsh)이지만 여전히 읽을 때 .profile.

따라서 원하는 POSIX 구문이 아니라 POSIX .profile와 호환되는 구문 (for sh) bashzsh해당 쉘을 사용하는 경우 (Bourne 쉘도 읽을 수 .profile있지만 Linux 기반 시스템에서는 일반적으로 발견되지 않는 Bourne 일 수도 있음) ).

checkbashismsbashism 을 찾는 데 도움이 되지만 zshor 와 호환되지 않는 POSIX 구문을 가리킬 수 없습니다 bash.

여기서 대화 형 로그인 쉘에서 읽지 않는 버그 bash의 해결 방법과 같은 특정 코드 를 사용하려면 일반적인 세션을 배치 하기 전이나 후에 소스 코드를 사용 하는 것이 좋습니다. 초기화).bash~/.bashrc~/.bash_profile~/.profile


checkbashisms사용 된 변수로 인해 전달되지 않습니다 .
Thomas Dickey

2
@ThomasDickey, 예. 그러나 checkbashisms 보고서를 무시 해야하는 경우입니다. 지금까지 제공된 다른 모든 솔루션은 상당히 나쁩니다.
Stéphane Chazelas

@ StéphaneChazelas 당신은 다른 모든 솔루션이 더 나쁘다고 말합니다. $0이 특정한 경우에 사용 하는 데 어떤 문제가 있습니까?
Anthony G-

2
@AnthonyGeoghegan 그것은이라는 bash와이라는 sh다른 쉘을 구별하지 않습니다 sh.
Gilles 'SO- 악마 그만

또한 dashbash가 아닌 다른 쉘이 잘못 호출 된 경우 잘못된 긍정을 제공합니다 argv[0] == "bash".
Kevin

17

보통 $0이 목적으로 사용 합니다. 당신이 링크 한 사이트에 서 있습니다 :

0
   (Zero.) Expands to the name of the shell or shell script.

너무 간단합니다! 나는 $0쉘 스크립트의 이름 을 사용 하는 데 익숙해 져서 현재 쉘을 참조 할 수 있다는 것을 잊어 버렸습니다. 감사!
Anthony G-15

1
평소와 같이,이 규칙은 잘 작동하는 모든 프로그램에서 존중하지만 악의적 인 프로그램은 exec호출 프로그램이 바이너리와 문자열을 별도로 실행하여 인수로 전달되도록 바이너리를 식별 할 수 있기 때문에 가족의 다양한 시스템 호출을 사용하여 엉망이 될 수 있습니다 0.
dmckee

그것은 .profile :) 귀여운 작동
Rob

5

일반적으로 SHELL 환경 변수는 기본 쉘을 알려줍니다. .bashrc 파일을 수동으로 소싱 할 필요는 없습니다 (true는 아님). bash는 자동으로 $ HOME 디렉토리에 있는지 확인해야합니다.

다른 옵션은 다음과 같은 작업을 수행하는 것입니다.

 ps -o cmd= $$

현재 프로세스의 명령 (인수없이, 값이없는 =는 열 헤더를 표시하지 않습니다)를 알려줍니다. 출력 예 :

 $ps -o cmd= $$
 bash
 $sh
 $ps -o cmd= $$
 sh

최신 정보:

나는 정정되었다! :)

아래 설명과 https : //.com/questions/415403/whats-the-difference-between-bashrc-bash-profile-and-environment에서 언급했듯이 .bashrc는 항상 소스가 아닙니다.

따라서 .bashrc를 .bash_profile로 옮기고 테스트하지 않아도 작동하는지 확인할 수 있습니다. 그렇지 않은 경우 위의 테스트가 있습니다.


1
.bashrc실제로 로그인 쉘에서 제공하지는 않지만 .profile(있는 경우) 또는 .bash_profile있습니다. SHELLPOSIX에 의해 지정되지 않았고 불행히도에 대한 cmd형식 옵션 도 없습니다 ps.
Anthony G-

1
이것이 내가 사용하는 것이지만 악의적 인 조작의 대상이기도합니다.
dmckee

(가) 동안 주 ps -o cmd= $$거의 모든 곳에서 작동해야는 $SHELL변수는 완전히 무관하다. 이는 사용자의 기본 쉘이며 현재 실행중인 쉘 또는 쉘 스크립트를 실행중인 쉘과 관련이 없습니다.
terdon

2
아니, 아니 ~/.profile로그인 쉘로 시작할 때 많은 쉘이 읽 힙니다 . 예를 들어, 당신 $SHELL은 할 수 있고 csh실행할 수 있습니다 bash -l. bash는 로그인 셸로 시작하므로을 읽지 ~/.profile$SHELL여전히을 가리 킵니다 csh. 또한 .profile다른 스크립트에서 명시 적으로 제공 할 수도 있습니다. OP는 최대한의 견고성을 추구하기 때문에 모든 종류의 사례를 고려해야합니다. 어쨌든 $SHELL현재 실행중인 쉘에 대한 유용한 정보를 제공하지 않습니다.
terdon

2
FWIW, 나도 SHELLPOSIX에 의해 지정되지 않은 것에 대해 수정되었습니다 : pubs.opengroup.org/onlinepubs/9699919799/basedefs/…
Anthony G-Monica의 정의

4

이 질문은 현재 쉘 뿐만 아니라 사용자의 로그인 쉘 을 appeases 방식으로 요청합니다 . 그것이 사용자가 로그인 한 쉘이라면, 나는 다음과 같은 것을 사용합니다 .checkbashisms/etc/passwd

MY_UID=$(id -u)
MYSHELL=$(awk -F: '$3 == '$MY_UID'{ print $7; }' </etc/passwd )

물론 사용자는 로그인 후 새로운 쉘을 시작할 수 있습니다. 물론, 하나는 bash이고 다른 하나는 bash가 아닌 경우 bash의 환경 변수 테스트가 도움이되지 않을 수 있습니다.

일부는 파일 getent대신 사용 하기를 원할 수도 있습니다 passwd(그러나 그것은 질문의 범위에 있지 않습니다).

LDAP에 대한 의견과에 대한 제안에 따라이 logname대체 양식을 사용할 수 있습니다.

MY_NAME=$(logname)
MYSHELL=$(getent passwd | awk -F: '$1 ~ /^'$MY_NAME'$/ {print $7;}' )

테스트하는 동안 logname입력이 리디렉션 되는 것을 좋아하지 않는다는 것을 알았습니다 (따라서 표현식을 나눕니다). 빠른 검사 쇼 getent는 언급 된 플랫폼에서 작동해야합니다 (원래 질문에서 제공되었지만).


1
사용자 데이터베이스가 / etc / passwd (LDAP / NIS / mysql ... 아님)에 있고 사용자 ID 당 하나의 사용자 이름 만 있다고 가정합니다. (에 대해 첫 번째 열을 확인하는 것이 좋습니다 $(logname)).
Stéphane Chazelas

iirc, POSIX는 필요한 유틸리티를 정의하지 않습니다 (또는 내 대답에 사용했을 것입니다). 사용 여부 id또는 사용자 수정 가능 변수는 다른 선택입니다.
Thomas Dickey

1
내가 말한 것을 참고 $(logname)하지 $LOGNAME. 사용자 ID와 로그인 쉘은 모두 로그인시 사용 된 사용자 이름에서 파생됩니다. 사용자 ID 당 하나의 사용자 이름 만있는 시스템을 제외하고는 사용자 ID에서 로그인 쉘로 되돌릴 수 없습니다. 또는 IOW, 사용자 데이터베이스의 기본 키는 uid가 아닌 사용자 이름입니다.
Stéphane Chazelas

다른 관점에서 오는 답변에 대해 @ThomasDickey에게 감사드립니다. 그러나 그것은 내가 생각했던 것보다 조금 더 복잡합니다 ( jimmijStéphane 의 답변 과 비슷 합니다). 쉘 구성 파일을 버전 제어로 설정하는 이유 중 하나는 현재 정기적으로 로그인하는 모든 시스템에서 환경을 구성하는 것입니다. Cygwin, Ubuntu 및 CentOS (5 및 7 모두 사용자 용 Active Directory 사용) 입증). 이런 이유로, 나는 논리를 가능한 한 단순하게 유지하는 것을 선호합니다.
Anthony G-
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.