#! / usr / bin / env bash가 #! / bin / bash보다 우수한 이유는 무엇입니까?


212

이 사이트에 대한 권고 (를 포함하여 여러 곳에서 본 적이 선호 배쉬 오두막을? 무엇을한다 ,)를 사용하기 #!/usr/bin/env bash에 우선 #!/bin/bash. 나는 진취적인 개인이 사용하는 #!/bin/bash것이 잘못되었다는 것을 보았고 그렇게하면 bash 기능이 손실 될 것입니다.

모든 말은, 순환하는 모든 드라이브가 본질적으로 단일 마스터 드라이브의 복제 본인 엄격하게 제어되는 테스트 환경에서 bash를 사용합니다. 이식성 인수는 필자의 경우에 반드시 해당되는 것은 아니지만 이해합니다. #!/usr/bin/env bash대안 을 선호하는 다른 이유가 있습니까? 이식성이 문제라고 가정하면 기능을 사용할 수없는 이유가 있습니까?


7
반드시 더 좋은 것은 아닙니다. 이 질문 과 unix.stackexchange.com에 대한 답변 을 참조하십시오 . (이것은 복제본으로 마감하기로 투표했지만 여러 사이트에서 그렇게 할 수는 없다고 생각합니다.)
Keith Thompson

2
@zigg의 답변 외에도에 env위치하지 않을 수 있습니다 /usr/bin. Shebang 의견은 모두 나쁜 아이디어 IMHO입니다. 기본 스크립트 인터프리터가 shebang 주석을 처리하지 않으면 주석 일뿐입니다. 그러나 스크립트 인터프리터가 shebang 주석을 처리 할 수 ​​있고 bash의 경로를 알고있는 경우 경로가 너무 길지 않은 경우 (아마도) 스크립트 경로를 지정하지 않으면 절대 경로를 사용하여 호출하지 않을 이유가 없습니다. / bin에 bash가없는 시스템에 그런 다음, 이전에 언급 한 경고는 이식성이 관련되어 있으므로이 경우에 적용됩니다.

1
@KeithThompson, 링크 주셔서 감사합니다. 아마도 질문을 게시하기 전에 답변을 찾은 것이 약간 좁았습니다. (1) linux / unix / posix / etc ...는 회색이며, (2) 정답을 가지고 있다고 주장하는 사람은 누구나 특정 시나리오에 대한 정답을 가지고 있습니다.
spugm1r3

3
POSIX / Unix에서 많은 것들의 동작은 잘 정의되어 있습니다. 위치가 항상 명확하지는 않습니다. 일도처럼 존재해야 /etc하거나 /bin/sh. bash대부분의 유닉스 계열 시스템을위한 애드온입니다. Linux로만 bash보장되며로 /bin연결되어있을 가능성이 높습니다 /bin/sh. 리눅스는 많은 사람들에게 현대의 사실상 유닉스가 되었기 때문에 리눅스 이외의 시스템이 존재한다는 사실을 잊어 버렸습니다. 당신이 말했기 때문에 아래의 나 자신의 대답에서 나는 리눅스를 가정했다 bash. 내가 작업 한 많은 BSD 상자에는 설치하지 않았습니다.
Sean Perry

2
@Keith-Bash의 경우 (다른 질문에서 Python과 반대) ... OpenBSD에는 /bin/bash. Bash는 기본적으로 설치되지 않습니다. 당신이 그것을 원한다면, 당신은해야합니다 pkg install bash. 설치되면에 위치 /usr/local/bin/bash합니다. /bin/bashOpenBSD 에는 아무것도 설치되어 있지 않습니다 . Shebang #!/bin/bash은 오류가 발생하여 #!/usr/bin/env bash성공합니다.
jww

답변:


229

#!/usr/bin/env검색 PATH을위한 bash, 그리고 bash항상하지 /bin특히 비 - 리눅스 시스템에서. 예를 들어, OpenBSD 시스템에서는 /usr/local/bin옵션 패키지로 설치되었으므로에 있습니다.

당신이 절대적 경우 확인 bash/bin항상있을 것이다, 전혀 해를 끼치 지 당신에 직접 퍼팅 없다 오두막 -하지만 스크립트와 프로그램 모두 우리가 처음에 그들이 가지고있는 것으로 판단 것 이상의 삶을 가지고 있기 때문에 나는 반대 권하고 싶습니다.


29
무엇에 대한 env위치? POSIX는 그것을 강제하지 않습니다.
Julio Guerra

1
@JulioGuerra 메일을 처리하는 데 사용할 수 있는 /usr/lib/sendmail(또는 더 최근의 /usr/sbin/sendmail) 바이너리를 갖는 것과 마찬가지로 /usr/bin/env, env shebang이 일반적인 관행이기 때문에 유닉스 계열 시스템에 가장 관심이 있습니다 . 사실상 표준 인터페이스입니다.
zigg

8
@zigg 정말 UN * X입니다 ... <-:에 대한 표준 위치를 갖는 것이 가장 중요 env하지만, 표준 위치 (소프트 링크 일 수 있음)는 없습니다 bash. 말할 것도없이 왜 hashbang이을 정확히 받아들이지 않고을 #!bash사용하는 PATH대신을 사용하십시오 env. 신인에게는 충분히 혼란스럽지 않습니다.
ddekany

1
@JulioGuerra 위키 백과에 따르면 당신은 사실입니다. 대신, "더 가능성이 높습니다". 위키 백과는 말한다 This mostly works because the path /usr/bin/env is commonly used for the env utility여기 ) en.wikipedia.org/wiki/Shebang_(Unix - 우리는 털어해야한다 env가 "아마도"모든 시스템에서 서비스를 제공합니다.
Xavi Montero

2
@XaviMontero : 나는 시스템을 사용한 적이 env있었다 /binNOT IN을, /usr/bin(하지 않도록하는 일 가능성이 SunOS의 4). 요즘 /usr/bin/env#!/usr/bin/env해킹 의 인기 때문에 이용 가능할 것 입니다.
키이스 톰슨

39

bash의 표준 위치는 /bin입니다. 모든 시스템에서 이것이 사실이라고 생각합니다. 그러나 해당 버전의 bash가 마음에 들지 않으면 어떻게해야합니까? 예를 들어 bash 4.2를 사용하고 싶지만 Mac의 bash는 3.2.5입니다.

bash를 다시 설치할 수는 /bin있지만 나쁜 생각 일 수 있습니다. OS를 업데이트하면 덮어 씁니다.

그러나에 bash를 /usr/local/bin/bash설치하고 PATH를 다음과 같이 설정할 수 있습니다.

PATH="/usr/local/bin:/bin:/usr/bin:$HOME/bin"

이제,을 지정 bash하면에서 오래된 오래된 /bin/bash것이 아니라 새롭고 빛나는 에서을 얻 습니다 /usr/local/bin. 좋은!

내 쉘 스크립트를 제외하고는 !# /bin/bashshebang이 있습니다. 따라서 쉘 스크립트를 실행할 때 연관 배열이없는 구식 버전의 bash를 얻습니다.

사용 /usr/bin/env bash하면 내 PATH에있는 bash 버전이 사용 됩니다. PATH를 설정하여 /usr/local/bin/bash실행하면 스크립트가 사용할 bash입니다.

bash로 이것을 보는 것은 드물지만 Perl과 Python에서는 훨씬 일반적입니다.

  • 안정성에 중점을 둔 특정 유닉스 / 리눅스 릴리스 는 때때로이 두 스크립팅 언어의 출시로 뒤쳐져 있습니다. 얼마 전, RHEL의 Perl은 8 년 된 Perl 버전 인 5.8.8이었습니다! 더 현대적인 기능을 사용하려면 자신의 버전을 설치해야합니다.
  • Perlbrew 및 Pythonbrew와 같은 프로그램을 사용하면 이러한 언어의 여러 버전을 설치할 수 있습니다. 원하는 버전을 얻기 위해 PATH를 조작하는 스크립트에 의존합니다. 경로를 하드 코딩하면 brew에서 스크립트를 실행할 수 없습니다 .
  • 펄과 파이썬이 대부분의 유닉스 시스템에 포함 된 표준 패키지가 아니었던 것은 그리 오래 전이 아닙니다. 즉,이 두 프로그램이 설치된 위치를 알 수 없었습니다. 아래에 있었습니까 /bin? /usr/bin? /opt/bin? 누가 알아? 사용 #! /usr/bin/env perl한다는 것은 알 필요가 없다는 것을 의미했습니다.

그리고 왜 당신은 사용하지 않아야 #! /usr/bin/env bash

경로가 shebang에 하드 코딩되면 해당 인터프리터와 함께 실행해야합니다. 따라서 #! /bin/bash기본 설치된 버전의 bash를 사용해야합니다. bash 기능은 매우 안정적이므로 (Python 3.x에서 2.x 버전의 Python 스크립트를 실행 해보십시오) 특정 BASH 스크립트가 작동하지 않을 가능성이 거의 없으며이 bash 스크립트가이 시스템 및 다른 시스템에서 사용되기 때문에 비표준 버전의 bash를 사용하면 원하지 않는 결과가 발생할 수 있습니다. 안정적인 표준 버전의 bash를 쉘 스크립트와 함께 사용하고 싶을 가능성이 큽니다. 따라서 아마도 내 shebang에서 경로를 하드 코딩하고 싶을 것입니다.


5
"bash의 표준 위치는 / bin입니다."(표준 문서를 인용 할 수없는 경우가 아니라면) 대부분의 Linux 배포판과 macos에서 "일반적인"위치라는 것이 더 정확할 것입니다. 유닉스 시스템에서는 일반적으로 표준 입니다 (특히 대부분의 * bsds의 위치가 아닙니다).
tesch1

13

호출 bash하는 것은 약간 과잉입니다. bash~ / bin에 자신과 같은 바이너리 가 여러 개가 아니라면 코드에 올바른 것이있는 $ PATH에 의존한다는 것을 의미합니다.

python그래도 편리합니다 . 대체 python바이너리가 사용되는 랩퍼 스크립트 및 환경이 있습니다 .

그러나 이진 파일이 실제로 원하는 이진 파일이라고 확신하는 한 이진 파일의 정확한 경로를 사용하면 아무것도 손실되지 않습니다.


에 주목하십시오 python. 나는 python찾을 수있는 장소의 수를 잃어 버렸다 😀
zigg

2
그 합의 /usr/bin/env는 VIRTUALENV 사용 특히, 파이썬에 더 유용하다.
Dennis

10

Bash in /bin, FreeBSD 및 OpenBSD 가없는 시스템이 많이 있습니다 . 스크립트가 여러 다른 Unices에 이식 가능해야하는 경우 #!/usr/bin/env bash대신 대신 사용할 수 있습니다 #!/bin/bash.

이것은 사실이 아닙니다 sh. Bourne의 호환 스크립트 나는 독점적으로 사용할 #!/bin/sh내가이 존재 거의 모든 유닉스 생각하기 때문에, sh/bin.


우분투 18.04 /bin디렉토리 에서을 참조하십시오 sh -> dash. 에 상징적으로 연결되어 dash우분투의 데비안 특성을 나타냅니다. : 모든 개별 취향에 귀결 실현하기 위해이 세 가지 명령 문자열을 실행 which bash한 후 which sh다음 which dash.
noobninja

0

bash시스템에서 사용 가능한 모든 항목을 확인하려면 다음과 같은 스크립트로 기본 프로그램을 래핑하는 것이 좋습니다. 사용하는 버전을 더 잘 제어하는 ​​것이 좋습니다.

#! /usr/bin/env bash

# This script just chooses the appropriate bash
# installed in system and executes testcode.main

readonly DESIRED_VERSION="5"

declare all_bash_installed_on_this_system
declare bash

if [ "${BASH_VERSINFO}" -ne "${DESIRED_VERSION}" ]
then
    found=0

    all_bash_installed_on_this_system="$(\
        awk -F'/' '$NF == "bash"{print}' "/etc/shells"\
        )"

    for bash in $all_bash_installed_on_this_system
    do
        versinfo="$( $bash -c 'echo ${BASH_VERSINFO}' )"
        [ "${versinfo}" -eq "${DESIRED_VERSION}" ] && { found=1 ; break;}
    done
    if [ "${found}" -ne 1 ]
    then
        echo "${DESIRED_VERSION} not available"
        exit 1
    fi
fi

$bash main_program "$@"

0
 #!/usr/bin/env bash

시스템 환경 변수에서 bash 실행 파일 경로를 찾기 때문에 확실히 좋습니다.

Linux 쉘로 이동하여 다음을 입력하십시오.

env

모든 환경 변수를 인쇄합니다.

쉘 스크립트로 이동하여 다음을 입력하십시오.

echo $BASH

스크립트에서 올바른 shebang 경로를 빌드하는 데 사용해야하는 bash 경로 (환경 변수 목록에 따라)를 인쇄합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.