왜 경로가없는 세방을 사용하지 않습니까?


24

인터프리터에 대한 경로를 지정하는 대신 인터프리터의 이름을 가지며 쉘이 $ PATH를 통해 찾을 수 있도록하는 shebang을 가질 수 있습니까?

그렇지 않다면 이유가 있습니까?


답변:


20

PATH 조회는 일반적인 환경 변수와 마찬가지로 사용자 공간에서 표준 C 라이브러리의 기능입니다. 커널은 호출자 execve에서 새로운 프로세스로 환경을 넘길 때를 제외하고는 환경 변수를 보지 못합니다 .

커널은 경로 execve( execvpPATH 조회 수행 과 같은 랩퍼 기능에 달려 있음 ) 또는 shebang ( execve호출을 내부적으로 다소 라우팅하는 경로)에 대한 해석을 수행하지 않습니다 . 따라서 shebang¹에 절대 경로를 넣어야합니다. 원래 오두막 구현은 단지 몇 줄의 코드이며, 그것은 크게 이후 확장되지 않았습니다.

유닉스의 첫 번째 버전에서, 쉘은 스크립트를 호출하고 있음을 알았을 때 자체 호출 작업을 수행했습니다. Shebang은 몇 가지 이유로 커널에 추가되었습니다 ( Dennis Ritchie이론적 근거 요약 :

  • 호출자는 실행할 프로그램이 쉘 스크립트인지 원시 바이너리인지 걱정할 필요가 없습니다.
  • 스크립트 자체는 호출자 대신 사용할 인터프리터를 지정합니다.
  • 커널은 로그에서 스크립트 이름을 사용합니다.

경로없는 shebang은 환경 변수 및 프로세스에 액세스하기 위해 커널을 보강하거나 커널 PATH이 PATH 조회를 수행하는 사용자 공간 프로그램을 실행하도록해야합니다. 첫 번째 방법은 커널에 과도한 양의 복잡성을 추가해야합니다. 두 번째 방법은 이미 #!/usr/bin/envshebang으로 가능합니다 .

¹ 상대 경로를 설정하면 프로세스의 현재 디렉토리 (스크립트가 포함 된 디렉토리가 아님)로 상대적으로 해석되므로 shebang에서 거의 유용하지 않습니다.


2
아닙니다. 커널은 execveshebang에 상대 경로를 갖는 것이 의미가 없지만 shebang에 절대 경로를 요구하지 않습니다 .
Stéphane Chazelas 2016 년

3
"shebang이 execve 호출을 내부적으로 다시 라우팅하는 방법"에 대해 궁금한 사람은 실제로 필요한 실행 파일에서 인터프리터를 실행하기위한 일반적인 메커니즘의 일부입니다. 동적으로 링크 된 ELF 실행 파일은 다음과 같이 "해석"됩니다 /lib64/ld-linux-x86-64.so.2( ldd출력 참조 ). 리눅스는 그것을 완전히 일반화시킨다 : binfmt2.1.43 이후 지원은 인터프리터 경로 / 매직 넘버 또는 파일 확장자 쌍을 등록하게한다. PE32 를 실행할 때, Java 클래스 및 jar 파일을 .exe호출 wine할 때 등을 호출 할 수 있습니다 java.
Peter Cordes

#! / usr / bin / env -S [shebang]은 경로를 몰라도 노드를 실행하는 데 필요했습니다 (nvm 사용-원래 예상했던 것과 다른 위치에 배치).
TamusJRoyce

-S는 coreutils 8.30 이후에만 사용 가능합니다. gitlab.com/gnuwget/wget/commit/…을 참조하십시오 .
팀 Ruehsen rockdaboot

19

눈을 맞추는 것보다 더 많은 일이 있습니다. #!행은 유닉스 또는 리눅스 커널에 의해 해석되며 #!쉘의 측면이 아닙니다. 이것은 PATH커널이 무엇을 실행할지 결정할 때 실제로 존재하지 않음을 의미합니다 .

실행할 실행 파일을 모르거나 perl이식 가능한 방식 으로 호출하는 방법을 모르는 가장 일반적인 방법 은을 사용하는 것 #!/usr/bin/env perl입니다. 커널은 환경 변수 /usr/bin/env를 상속하는를 실행 PATH합니다. env(이 예에서) 발견 perlPATH와 사용하는 execve(2)시스템 호출은 실행 커널 얻기 위해 perl실행.


4
$ strace sleep 1
execve("/usr/bin/sleep", ["sleep", "1"], [/* 99 vars */]) = 0

전체 경로로의 변환은 쉘에 의해 수행됩니다 (일반적으로 사용자 공간에서). 커널은 직접 액세스 할 수있는 파일 이름 / 경로를 예상합니다.

PATH 변수를 통해 시스템이 실행 파일을 찾도록하려면 shebang을로 다시 작성할 수 있습니다 #!/usr/bin/env EXEC.

그러나이 경우 검색을 수행하는 것은 커널이 아닙니다.


1
전체 경로로의 변환은 쉘에 의해 수행됩니다. 감사합니다. 내가 알다시피, 쉘은 2 개의 인수 strace로 실행 중입니다 ( /usr/bin/strace어느 시점에서 변환됩니다 ).
Alois Mahdal 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.