“#! / usr / bin / env bash”와“#! / usr / bin / bash”의 차이점은 무엇입니까?


372

Bash 스크립트의 헤더에서 두 문장의 차이점은 무엇입니까?

  1. #!/usr/bin/env bash

  2. #!/usr/bin/bash

나는 상담을 할 때 env 맨 페이지를 ,이 정의를 얻을 :

 env - run a program in a modified environment

무슨 뜻이에요?


7
이 질문내 대답을 참조하십시오 .
키이스 톰슨

6
"프로그래밍 또는 소프트웨어 개발과 관련하여"이 질문이 닫힌 이유를 누가 알 수 있습니까?
tarrsalah

1
나는 그것이 주제에 맞지 않다는 것에 동의하지만, 아마도 이것 과 같은 다른 몇 가지 질문의 사본 일 것 입니다.
Keith Thompson

16
이 질문은 주제를 벗어난 것으로 표시해서는 안됩니다. "주제"로 표시하려면 점수가 3000 이상인 5 명만 있으면 다시 열 수 있습니다. 프로그래밍에 대한 질문입니다.
Danijel-James W

3
나는 충격을 받았다. 리눅스 문서가 긴장을 풀고 있다는 사실에 놀랐다. xkcd.com/703 git-man-page-generator.lokaltog.net
allyourcode

답변:


323

명령을 실행하면 /usr/bin/env현재 환경 에서 프로그램의 기본 버전이 무엇이든 찾을 수 있다는 이점이 있습니다.

이 방법은 시스템의 특정 위치에서 찾을 필요가 없습니다. 경로는 시스템마다 다른 위치에있을 수 있기 때문입니다. 그것이 당신의 길에있는 한 그것을 찾을 것입니다.

한 가지 단점은 POSIX가 라인을 해석하는 방법에 대해 모호 하고 Linux가 첫 번째 이후의 모든 것을 해석하기 때문에 /usr/bin/env awk -fLinux를 지원하려는 경우 둘 이상의 인수를 전달할 수 없다는 것입니다 (예를 들어 쓸 수 없음 ) 단일 인수를 나타내는 공백. 이 문제를 해결하기 위해 일부 버전에서 사용할 수 있지만 스크립트는 이식성이 떨어지고 상당히 최신 시스템에서 중단됩니다 (예 : 나중에 우분투 16.04)./usr/bin/env -Senv

또 다른 단점은 명시 적 실행 파일을 호출하지 않기 때문에 실수 및 다중 사용자 시스템 보안 문제 ( bash예를 들어 누군가가 경로에서 실행 파일을 호출 한 경우)의 가능성이 있다는 것입니다.

#!/usr/bin/env bash #lends you some flexibility on different systems
#!/usr/bin/bash     #gives you explicit control on a given system of what executable is called

경우에 따라 첫 번째 방법이 선호 될 수 있습니다 (실행 파일을 다시 작업하지 않고도 여러 버전의 Python으로 Python 스크립트 실행). 그러나 보안에 중점을 두는 상황에서는 코드 삽입 가능성이 제한되므로 후자가 선호됩니다.


22
또 다른 단점은 인터프리터에게 추가 인수를 전달할 수 없다는 것입니다.
Keith Thompson

1
@KeithThompson : 잘못된 정보. / usr / bin / env를 사용하여 옵션을 기본 통역사에 전달할 수 있습니다!
Gaurav Agarwal

4
@GauravAgarwal : 내 시스템에 없습니다. 이 한 줄만 포함 된 스크립트 : #!/usr/bin/env echo Hello불평 : /usr/bin/env: echo Hello: No such file or directory. 분명히 그것은에 echo Hello대한 단일 논쟁으로 취급 합니다 /usr/bin/env.
Keith Thompson

1
@ AndréLaszlo : env명령은 확실히 인수가 명령에 전달되도록합니다. 문제는 #!라인 의 의미론이며 커널에 따라 다릅니다. 최신 Linux 커널은와 같은 것을 허용 #!/usr/bin/env command args하지만 이전 Linux 커널 및 다른 시스템은 허용하지 않습니다.
Keith Thompson

1
코드 블록에 왜 백틱이 있습니까? 그것들을 제거해서는 안됩니까?
Benjamin W.

64

를 사용 #!/usr/bin/env NAME하면 쉘이 $ PATH 환경 변수에서 NAME의 첫 번째 일치 항목을 검색합니다. 절대 경로를 모르거나 검색하지 않으려는 경우 유용 할 수 있습니다.


9
적어도 env가 어디에 있는지 알아야합니다 :).
ᐅ devrimbaris

1
훌륭한 답변입니다. "시스템 구성에 따라 프로그램을 선택합니다"라고 말하지 않고 env shebang이하는 일을 간결하게 설명합니다.
De Novo

13

/usr/bin/bash/env 명령을 사용하여 에서처럼 인터프리터의 경로를 명시 적으로 정의하는 대신 , 인터프리터는 처음 발견 된 위치에서 검색 및 실행됩니다. 여기에는 단점과 단점이 있습니다


대부분의 시스템에서 기능은 동일하지만 bash 및 env 실행 파일의 위치에 따라 다릅니다. 그러나 이것이 환경 변수에 어떤 영향을 미치는지 확실하지 않습니다.
safay

2
"인터프리터에게 전체 경로를 제공하여 env를 사용하지 않고 인터프리터를 지정할 수 있습니다. 문제는 다른 컴퓨터 시스템에서 정확한 경로가 다를 수 있다는 것입니다. 대신 env를 사용하면 인터프리터가 검색되어 위치합니다. 이렇게하면 스크립트가 더 이식성이 뛰어나지 만 실행 가능한 검색 경로의 모든 디렉토리에서 일치하는 항목을 검색하기 때문에 잘못된 인터프리터가 선택 될 위험이 높아집니다. env 바이너리의 경로는 머신마다 다를 수 있습니다. "-Wikipedia
Mike Clark

10

쉘 스크립트가로 시작 #!/bin/bash하면 항상 bashfrom에서 실행됩니다 /bin. 그들은 그러나 시작하면 #!/usr/bin/env bash, 그들은 검색합니다 bash에서 $PATH다음 그들이 찾을 수있는 첫 번째로 시작합니다.

이것이 왜 유용한가? bashbash 4.x 이상이 필요한 스크립트 를 실행하려고 하지만 시스템에 bash3.x 만 설치되어 있고 현재 배포판에 최신 버전이 제공되지 않거나 관리자가 아니며 해당 시스템에 설치된 내용을 변경할 수없는 경우 .

물론 bash 소스 코드를 다운로드하고 자신의 bash를 처음부터 작성 ~/bin하여 예를 들어 배치 할 수 있습니다. 그리고 당신은 또한 수정할 수 있습니다 $PATH당신의 변수를 .bash_profile포함하는 파일의 ~/bin첫 번째 항목 (AS PATH=$HOME/bin:$PATH~의 확장되지 않습니다 $PATH). 이제을 호출 bash하면 셸은 먼저 $PATH순서대로 셸을 찾으 므로으로 시작하여을 ~/bin찾습니다 bash. 스크립트가을 bash사용하여 검색하는 경우에도 동일한 작업 #!/usr/bin/env bash이 수행되므로 이러한 스크립트는 이제 사용자 정의 bash빌드를 사용하여 시스템에서 작동합니다 .

한 가지 단점은 예기치 않은 동작으로 이어질 수 있다는 것입니다. 예를 들어 동일한 컴퓨터에서 동일한 스크립트가 다른 환경에 따라 다른 인터프리터 또는 다른 검색 경로를 가진 사용자와 함께 실행되어 모든 종류의 두통이 발생할 수 있습니다.

가장 큰 단점 env은 일부 시스템은 하나의 인수 만 허용하므로 #!/usr/bin/env <interpreter> <arg>시스템이 <interpreter> <arg>하나의 인수로 표시되므로 (표현이 인용 된 것처럼 처리하므로) env이라는 인터프리터를 검색한다는 것 <interpreter> <arg>입니다. 이것은 env명령 자체 의 문제가 아니며 항상 여러 매개 변수를 전달할 수 있지만 호출하기 전에이 줄을 구문 분석하는 시스템의 shebang 파서와 함께 사용할 수 있습니다 env. 한편 이것은 대부분의 시스템에서 수정되었지만 스크립트가 휴대 성이 뛰어나기를 원한다면 실행할 시스템에서 수정되었다고 믿을 수는 없습니다.

sudo환경을 정리하도록 구성되지 않았거나 정리 $PATH에서 제외 된 경우와 같이 보안에 영향을 줄 수도 있습니다 . 이것을 보여 드리겠습니다 :

일반적으로 /bin잘 보호 된 장소이며 그곳에서만 root무엇이든 바꿀 수 있습니다. 그러나 홈 디렉토리는 실행중인 프로그램이 해당 디렉토리를 변경할 수 없습니다. 즉, 악성 코드가 bash숨겨진 디렉토리에 가짜 를 배치하고 .bash_profile해당 디렉토리를에 포함하도록 수정하여 $PATH사용하는 모든 스크립트 #!/usr/bin/env bash가 가짜로 실행되도록 할 수 bash있습니다. 경우 sudo유지 $PATH, 당신은 큰 문제입니다.

예를 들어 도구가 ~/.evil/bash다음 내용 으로 파일 을 생성한다고 가정 해보십시오 .

#!/bin/bash

if [ $EUID -eq 0 ]; then
  echo "All your base are belong to us..."
  # We are root - do whatever you want to do
fi

/bin/bash "$@"

간단한 스크립트를 만들어 봅시다 sample.sh:

#!/usr/bin/env bash

echo "Hello World"

개념 증명 (을 sudo유지 하는 시스템에서 $PATH) :

$ ./sample.sh
Hello World

$ sudo ./sample.sh
Hello World

$ export PATH="$HOME/.evil:$PATH"

$ ./sample.sh
Hello World

$ sudo ./sample.sh
All your base are belong to us...
Hello World

일반적으로 고전적인 쉘 모두에 위치해야 /bin하고 어떤 이유가 그들을 배치하지 않으려면,에서 심볼릭 링크 배치 정말 문제가 아니라 /bin자신의 실제 위치에 그 점을 (또는 어쩌면 /bin그래서, 그 자체가 심볼릭 링크입니다) 나는 항상 함께 갈 것 #!/bin/sh하고 #!/bin/bash. 더 이상 작동하지 않으면 깨질 수있는 것이 너무 많습니다. POSIX가 이러한 위치를 요구하지는 않지만 (POSIX는 경로 이름을 표준화하지 않으므로 shebang 기능을 전혀 표준화하지도 않습니다) 시스템이을 제공하지 않더라도 /bin/sh여전히 이해할 수있을 정도로 일반적 입니다. #!/bin/sh그것으로 무엇을 해야하는지 알고 있으며 기존 코드와의 호환성을 위해서만있을 수 있습니다.

그러나 Perl, PHP, Python 또는 Ruby와 같은 최신의 비표준 선택적 인터프리터의 경우 실제로 어디에 위치해야하는지 지정되지 않았습니다. 그들은에서있을 수 /usr/bin있지만, 그들은뿐만 아니라에있을 수 있습니다 /usr/local/bin또는 완전히 다른 계층 분기 (에서 /opt/..., /Applications/...등). 그렇기 때문에 이들은 종종 #!/usr/bin/env xxxshebang 구문을 사용 합니다.


4

env에 대해 알지 못했을 때 스크립트 작성을 시작하기 전에이 작업을 수행했기 때문에 유용합니다.

type nodejs > scriptname.js #or any other environment

그런 다음 파일의 해당 줄을 shebang으로 수정했습니다.
내 컴퓨터의 nodejs가 / usr / bin / 또는 / bin /인지 항상 기억하지 못했기 때문에이 작업을 수행 했으므로 env매우 유용합니다. 아마도 이것에 대한 세부 사항이 있지만 이것이 내 이유입니다.

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