경로 없는 shebang을 사용하지 않는 이유는 무엇입니까?

경로 없는 shebang을 사용하지 않는 이유는 무엇입니까?

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

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

답변1

PATH 조회는 환경 변수와 마찬가지로 사용자 공간에서 표준 C 라이브러리의 기능입니다. 커널은 호출자로부터 환경 변수를 전달하지 않으면 환경 변수를 볼 수 없습니다.execve새로운 프로세스로.

execve커널은 (PATH 조회 수행과 같은 래퍼 함수에 따라 다름 execvp) 또는 shebang(거의 execve내부적으로 호출을 다시 라우팅하는) 에서 경로 해석을 수행하지 않습니다 . 따라서 shebang에 절대 경로를 넣어야 합니다. 이것원래 Shebang 구현단 몇 줄의 코드만 있으면 되며 그 이후로는 크게 확장되지 않았습니다.

Unix의 첫 번째 버전에서 쉘은 사용자가 스크립트를 호출하고 있음을 알아차렸을 때 자체 호출 작업을 수행했습니다. Shebang은 여러 가지 이유로 커널에 추가되었습니다(요약하자면데니스 리치의 기본:

  • 호출자는 실행될 프로그램이 쉘 스크립트인지 네이티브 바이너리인지 걱정할 필요가 없습니다.
  • 스크립트 자체는 호출자가 아닌 사용할 인터프리터를 지정합니다.
  • 커널 사용 로그의 스크립트 이름입니다.

경로 없는 shebang을 사용하려면 커널을 강화하여 환경 변수 및 프로세스에 액세스하거나 PATH커널이 PATH 조회를 수행하는 사용자 공간 프로그램을 실행하도록 해야 합니다. 첫 번째 접근 방식에서는 커널에 불균형적인 복잡성을 추가해야 합니다. 두 번째 방법은 이미 사용 가능합니다.#!/usr/bin/env셰르본.

1 상대 경로를 입력하면 (스크립트가 포함된 디렉토리가 아닌) 프로세스의 현재 디렉토리를 기준으로 해석되므로 shebang에서는 거의 사용되지 않습니다.

답변2

눈에 보이는 것보다 더 많은 일이 벌어지고 있습니다. #!행은 Unix 또는 Linux 커널에 의해 해석되며 #!셸의 측면이 아닙니다. 이는 PATH커널이 무엇을 실행할지 결정할 때 그것이 실제로 존재하지 않는다는 것을 의미합니다 .

이식 가능한 방식이나 이와 유사한 방식으로 실행하거나 호출할 실행 파일을 알지 못하는 경우를 처리하는 가장 일반적인 방법은 환경 변수를 상속하는 .kernel 실행을 perl사용하는 것입니다 . 이 예에서는 시스템 호출을 찾아서 사용하여 커널 에 실행 파일을 실행하도록 지시합니다.#!/usr/bin/env perl/usr/bin/envPATHenvperlPATHexecve(2)perl

답변3

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

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

시스템이 PATH 변수를 보고 실행 파일을 찾도록 하려면 shebang을 #!/usr/bin/env EXEC.

하지만 이 경우에도 검색을 수행하는 것은 커널이 아닙니다.

관련 정보