#! /빈/sh -
(또는 적어도) 종종 권장됩니다셰르본스크립트를 /bin/sh
(또는 #! /bin/bash -
bash, #! /bin/ksh -
ksh 등) 로 해석하도록 합니다.
왜 그냥 #! /bin/sh
또는 #!/bin/sh
?
그게 뭔데 -
?
답변1
이는 다음과 같이 작성해야 하는 이유와 유사합니다.
rm -- *.txt
설마
rm *.txt
.txt
현재 디렉토리에 이름 이 -
.
존재하다:
RM<매개변수>
<arg>
파일로 시작하면 -
옵션으로 간주되고, 그렇지 않으면 삭제할 파일로 간주됩니다. 존재하다
RM-<매개변수>
<arg>
파일 시작 여부에 관계없이 항상 삭제 대상으로 간주됩니다 -
.
에 대해서도 마찬가지입니다 sh
.
실행할 때
#! /bin/sh
일반적으로 다음과 관련됩니다.
execve("path/to/the-script", ["the-script", "arg"], [environ])
시스템은 이를 다음으로 변환합니다.
execve("/bin/sh", ["/bin/sh", "path/to/the-script", "arg"], [environ])
이것path/to/the-script
일반적으로 스크립트 작성자의 통제를 받지 않습니다. 작성자는 스크립트 복사본이 어디에 저장될지, 어떤 이름으로 저장될지 예측할 수 없습니다. 특히, 보장할 수는 없습니다.path/to/the-script
호출이 시작되지 않는 경우 -
(또는 +
문제일 수도 있음 sh
) 그래서 우리는필요이것 -
으로 옵션이 끝났습니다.
예를 들어, 내 시스템에는 zcat
(실제로 대부분의 다른 스크립트와 마찬가지로) 해당 조언을 따르지 않는 스크립트의 예가 있습니다.
$ head -n1 /bin/zcat
#!/bin/sh
$ mkdir +
$ ln -s /bin/zcat +/
$ +/zcat
/bin/sh: +/: invalid option
[...]
#! /bin/sh -
이제 왜 안 되냐고 물으실 수도 있습니다 #! /bin/sh --
.
#! /bin/sh --
POSIX 쉘과 함께 사용할 수 있지만 특히 #! /bin/sh -
고대 버전은 더 이전 버전 sh
으로 간주 sh
하고 옵션 종료를 오랫동안 표시하는 데 사용됩니다 . Bourne 쉘(70년대 후반부터)이 인수를 구문 분석하는 방식으로, 첫 번째 인수가 로 시작하면 이후의 모든 문자 는 옵션 이름으로 처리됩니다 . 이것이 멈추었고 Bourne과 같은 모든 후속 쉘은 이를 옵션의 끝을 표시하는 방법으로 처리했습니다.-
getopt()
--
-
-
-
-
Bourne 쉘(현대 Bourne과 유사한 쉘에서는 아님)에서는 #! /bin/sh -eu
이 문제를 해결할 수도 있습니다. 옵션이 첫 번째 인수만 고려하기 때문입니다.
자, 어떤 사람들은 우리가 여기서 현학적이라고 말할 수도 있습니다. 이것이 제가 이 글을 쓰는 이유입니다.필요위의 이탤릭체:
- 올바른 생각을 가진 사람은
-
또는 로 시작하는 스크립트를 호출하거나+
이름이 또는 로 시작하는 디렉토리에 스크립트를 넣지 않을 것입니다.-
+
- 설령 그렇게 했다고 하더라도, 첫 번째 사람은 자신들이 책임을 져야 하며 스크립트를 호출할 때 일반적으로 쉘이나
execvp()
/execlp()
유형 함수에서 발생한다고 주장할 것입니다. 이 경우 일반적으로 호출하여the-script
찾을 수 있습니다.$PATH
이 경우 시스템 호출에 대한 경로 인수는 일반적으로 (not 또는 )execve()
로 시작 하거나 현재 디렉터리에서 실행 하려는 것과 같습니다 (그런 다음 경로는 , is not로 시작합니다. 그것도 아니고 ) 시작하세요./
-
+
./the-script
the-script
./
-
+
이제는 이론 외에단정#! /bin/sh -
질문, 추천하는 또 다른 이유가 있습니다좋은 연습. 이는 여러 시스템이 여전히 setuid 스크립트를 지원하던 시절로 거슬러 올라갑니다.
다음을 포함하는 스크립트가 있는 경우:
#! /bin/sh
/bin/echo "I'm running as root"
스크립트는 -r-sr-xr-x root bin
권한과 마찬가지로 setuid 루트이며 일반 사용자가 실행할 때 이러한 시스템에서는
execve("/bin/sh", ["/bin/sh", "path/to/the-script"], [environ])
완료됩니다 root
!
사용자가 심볼릭 링크를 생성 /tmp/-i -> path/to/the-script
하고 실행하면 대화형 쉘( )이 로 -i
시작됩니다 ./bin/sh -i
root
이 문제를 해결할 수 -
있습니다(해결할 수 없습니다경쟁 조건 문제, 또는 일부 sh
구현(예: - 기반 구현은 in 없이 스크립트 매개변수를 찾습니다 ksh88
)./
$PATH
요즘에는 더 이상 setuid 스크립트를 지원하지 않는 시스템이 거의 없으며, 여전히 수행하는 일부 시스템(보통 기본적으로는 아님)은 이 문제와 콘테스트 조건을 해결하기 위해 스크립트를 읽기 위해 파일 설명자를 여는 작업을 수행하게 execve("/bin/sh", ["/bin/sh", "/dev/fd/<n>", arg])
됩니다 <n>
.
Bourne과 같은 쉘뿐만 아니라 대부분의 인터프리터에서도 비슷한 문제가 발생합니다. Bourne과 유사하지 않은 쉘은 일반적으로 -
옵션 끝 표시를 지원하지 않지만 일반적으로 지원합니다 --
(적어도 최신 버전에서는).
반품
#! /usr/bin/awk -f
#! /usr/bin/sed -f
문제 없습니다. 어떤 경우든 다음 인수는 옵션에 대한 인수로 간주되지만, -f
그렇다면 여전히 작동하지 않습니다(이 경우 대부분의 / 구현에서 /는 파일에서 나오지 않고 표준에서 나옵니다). 입력하다).path/to/script
-
sed
awk
sed
awk
-
또한 대부분의 시스템에서는 다음을 사용할 수 없습니다.
#! /usr/bin/env sh -
#! /usr/bin/perl -w --
대부분의 시스템과 마찬가지로 shebang 메커니즘은 다음만 허용합니다.하나인터프리터 경로 뒤에 오는 매개변수입니다.
#! /bin/sh -
VS를 사용할지 #!/bin/sh -
여부는 단지 취향의 문제일 뿐입니다. 나는 인터프리터 경로를 더 명확하게 만들고 마우스 선택을 더 쉽게 하기 때문에 전자를 선호합니다. 하나 있다전설에 따르면 일부 고대 버전의 Unix에는 이 공간이 필요했습니다.그러나 내가 아는 한 이것은 확인된 적이 없습니다.
Unix shebang에 대한 아주 좋은 참고 자료는 다음에서 찾을 수 있습니다.https://www.in-ulm.de/~mascheck/various/shebang
1 사용하더라도 추가 작업을 zsh
수행할 수 있으며 옵션의 끝을 표시할 수도 있습니다.#! /bin/zsh -eu-
-