Bash 스크립트의 헤더에서 두 문장의 차이점은 무엇입니까?
#!/usr/bin/env bash
#!/usr/bin/bash
나는 상담을 할 때 env
맨 페이지를 ,이 정의를 얻을 :
env - run a program in a modified environment
무슨 뜻이에요?
Bash 스크립트의 헤더에서 두 문장의 차이점은 무엇입니까?
#!/usr/bin/env bash
#!/usr/bin/bash
나는 상담을 할 때 env
맨 페이지를 ,이 정의를 얻을 :
env - run a program in a modified environment
무슨 뜻이에요?
답변:
명령을 실행하면 /usr/bin/env
현재 환경 에서 프로그램의 기본 버전이 무엇이든 찾을 수 있다는 이점이 있습니다.
이 방법은 시스템의 특정 위치에서 찾을 필요가 없습니다. 경로는 시스템마다 다른 위치에있을 수 있기 때문입니다. 그것이 당신의 길에있는 한 그것을 찾을 것입니다.
한 가지 단점은 POSIX가 라인을 해석하는 방법에 대해 모호 하고 Linux가 첫 번째 이후의 모든 것을 해석하기 때문에 /usr/bin/env awk -f
Linux를 지원하려는 경우 둘 이상의 인수를 전달할 수 없다는 것입니다 (예를 들어 쓸 수 없음 ) 단일 인수를 나타내는 공백. 이 문제를 해결하기 위해 일부 버전에서 사용할 수 있지만 스크립트는 이식성이 떨어지고 상당히 최신 시스템에서 중단됩니다 (예 : 나중에 우분투 16.04)./usr/bin/env -S
env
또 다른 단점은 명시 적 실행 파일을 호출하지 않기 때문에 실수 및 다중 사용자 시스템 보안 문제 ( 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 스크립트 실행). 그러나 보안에 중점을 두는 상황에서는 코드 삽입 가능성이 제한되므로 후자가 선호됩니다.
#!/usr/bin/env echo Hello
불평 : /usr/bin/env: echo Hello: No such file or directory
. 분명히 그것은에 echo Hello
대한 단일 논쟁으로 취급 합니다 /usr/bin/env
.
env
명령은 확실히 인수가 명령에 전달되도록합니다. 문제는 #!
라인 의 의미론이며 커널에 따라 다릅니다. 최신 Linux 커널은와 같은 것을 허용 #!/usr/bin/env command args
하지만 이전 Linux 커널 및 다른 시스템은 허용하지 않습니다.
를 사용 #!/usr/bin/env NAME
하면 쉘이 $ PATH 환경 변수에서 NAME의 첫 번째 일치 항목을 검색합니다. 절대 경로를 모르거나 검색하지 않으려는 경우 유용 할 수 있습니다.
/usr/bin/bash/
env 명령을 사용하여 에서처럼 인터프리터의 경로를 명시 적으로 정의하는 대신 , 인터프리터는 처음 발견 된 위치에서 검색 및 실행됩니다. 여기에는 단점과 단점이 있습니다
쉘 스크립트가로 시작 #!/bin/bash
하면 항상 bash
from에서 실행됩니다 /bin
. 그들은 그러나 시작하면 #!/usr/bin/env bash
, 그들은 검색합니다 bash
에서 $PATH
다음 그들이 찾을 수있는 첫 번째로 시작합니다.
이것이 왜 유용한가? bash
bash 4.x 이상이 필요한 스크립트 를 실행하려고 하지만 시스템에 bash
3.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 xxx
shebang 구문을 사용 합니다.