POSIX에서`#!`구문의 동작을 지정하지 않은 이유는 무엇입니까?


17

POSIX 스펙 의 쉘 명령 언어 페이지에서 :

쉘 명령 파일의 첫 번째 행이 "#!"문자로 시작하면 결과가 지정되지 않습니다.

#!POSIX 에서 동작을 지정하지 않은 이유는 무엇 입니까? 휴대 성이 뛰어나고 널리 사용되는 것은 불특정 한 행동을하게 될 것입니다.


1
표준은 구현을 특정 행동에 묶지 않도록 지정하지 않은 상태로 둡니다. 예를 들어 "로그인"은 "사용자가 시스템에 액세스하는 지정되지 않은 활동"입니다.
Kusalananda

2
POSIX는 실행 경로를 지정하지 않기 때문에 shebang 라인은 본질적으로 이식성이 없습니다. 나는 그것을 지정함으로써 그것을 많이 얻을 것이 확실하지 않다.
Michael Homer

1
@MichaelHomer, 확실하지 않습니까? 표준은 행에 경로가 무엇인지 말하지 않아도 인터프리터에 사용할 경로가 포함되도록 지정할 수 있습니다.
ilkkachu

1
@HaroldFischer 셸에서 해석되지 않는 한, OS 커널 (적어도 Linux에서는 수행되어 빌드 시간 동안이 지원을 실제로 비활성화 할 수 있음) 또는 exec()함수를 구현하는 라이브러리에 의해 해석됩니다 . 따라서 여러 쉘을 검사한다고해서 실제로 얼마나 이식성이 좋은지 알 수 없습니다.
Austin Hemmelgarn

2
@HaroldFischer 또한 POSIX 호환 OS에서도 동작이 일관되지 않습니다. Linux와 macOS는 다르게 동작합니다. Linux는 공백으로 셰방을 완전히 토큰 화하지 않습니다. macOS에서는 스크립트 인터프리터가 다른 스크립트가 될 수 없습니다. 또한 참조 en.wikipedia.org/wiki/Shebang_(Unix)#Portability
jamesdlin

답변:


21

나는 주로 다음과 같은 이유로 생각합니다.

  • 동작은 구현마다 크게 다릅니다. 자세한 내용은 https://www.in-ulm.de/~mascheck/various/shebang/ 을 참조 하십시오.

    같은 : 그것은 그러나 지금은 유닉스와 같은 구현 대부분의 최소 부분 집합 지정할 수 있습니다 #! *[^ ]+( +[^ ]+)?\n첫 번째 단어는 네이티브 실행 파일의 절대 경로입니다 (그 하나 또는 두 단어의 휴대용 파일 이름 문자 세트로만 포함), 물건이 아닌를 실행 파일이 setuid / setgid 인 경우 너무 길고 동작이 지정되지 않고 인터프리터 경로 또는 스크립트 경로가 argv[0]인터프리터에 전달되는지 여부가 구현에서 정의되었습니다 .

  • POSIX는 어쨌든 실행 파일의 경로를 지정하지 않습니다. 여러 시스템에서 유틸리티 - POSIX의 사전 한 /bin/ /usr/bin다른 곳 (Solaris 10의 같은 POSIX 유틸리티가 /bin/sh에있는 Bourne 쉘 및 POSIX의 하나입니다 /usr/xpg4/bin, 더 POSIX를 준수이지만, 경우 ksh93로 대체 솔라리스 11은 다른 대부분의 도구 /bin는 여전히 고대 비 POSIX 도구 입니다). 일부 시스템은 POSIX 시스템이 아니지만 POSIX 모드 / 에뮬레이션이 있습니다. 모든 POSIX는 시스템이 POSIXly 동작하는 문서화 된 환경이 필요합니다.

    예를 들어 Windows + Cygwin을 참조하십시오. 실제로 Windows + Cygwin을 사용하면 cygwin 응용 프로그램이 스크립트를 호출 할 때 기본 Windows 응용 프로그램이 아닌 she-bang이 사용됩니다.

    따라서 POSIX가 shebang 메커니즘을 지정한 경우에도 POSIX sh/ sed/ awk... 스크립트를 작성하는 데 사용할 수 없습니다 ( 옵션 종료를 허용하지 않으므로 신뢰할 수있는 sed/ awk스크립트 를 작성하는 데 shebang 메커니즘을 사용할 수 없습니다. 채점자).

이제 그것이 지정되지 않았다는 사실이 그것을 사용할 수 없다는 것을 의미하지는 않습니다 (물론, 그것이 #!평범한 의견 일 것으로 예상 되고 첫 번째 줄을 시작해서는 안된다고 말합니다 ). POSIX는 당신이 할 경우 보증하지 않습니다.

POSIX의에서 스크립트, 휴가를 그녀 - 뱅 떨어져 쓰기 : 내 경험에 의하면, shebangs를 사용하여 당신에게 쉘 스크립트를 작성하는 POSIX의 방법을 사용하는 것보다 휴대 성을 더 보장을 제공 sh구문과 희망은 어떤 스크립트는 POSIX의 준수를 호출 호출하는 sh이다, 그것을 스크립트가 올바른 도구로 올바른 환경에서 호출되지만 그렇지 않은 경우에는 알 수 있습니다.

다음과 같은 작업을 수행해야 할 수도 있습니다.

#! /bin/sh -
if : ^ false; then : fine, POSIX system by default
else
  # cover Solaris 10 or older. ": ^ false" returns false
  # in the Bourne shell as ^ is an alias for | there for
  # compatibility with the Thomson shell.
  PATH=`getconf PATH`:$PATH; export PATH
  exec /usr/xpg4/bin/sh - "$0" ${1+"$@"}
fi
# rest of script

Windows + Cygwin으로 이식하려면 파일 확장명 .bat또는 .ps1확장자를 사용 하여 파일 이름을 지정 하고 동일한 파일 에서 cygwin을 호출 cmd.exe하거나 powershell.exe호출하기 위해 유사한 트릭을 사용해야 할 수 있습니다 sh.


흥미롭게도, 이슈 5에서 : "구문 #!은 확장을 제공하고자하는 구현을 위해 예약되어 있습니다. 이식 가능한 응용 프로그램은 #!를 쉘 스크립트의 첫 줄로 사용할 수 없으며 주석으로 해석되지 않을 수 있습니다."
muru

@muru 스크립트가 POSIX를 실행하는 진정한 POSIX 시스템에서 스크립트를 이식성이 좋으면 POSIX sh에서 실행 하는 해시 뱅 라인이 필요하지 않습니다 sh.
Kusalananda

1
@ Kusalananda 그것은 execlp또는 execvp사용 된 경우에만 사실 입니까? 를 사용 execve하면 ENOEXEC가 발생합니까?
muru

9

모든 POSIX 호환 셸에서 동작이 일관된 것으로 보입니다. 여기 흔들 거실이 필요하지 않은 것 같습니다.

당신은 깊이보고하지 않습니다.

1980 년대에이 메커니즘은 사실상 표준화 되지 않았습니다 . Dennis Ritchie가이를 구현했지만 해당 구현은 우주의 AT & T 측면에서 대중에게 도달하지 못했습니다. BSD에서만 공개적으로 사용 가능하고 알려졌습니다. AT & T Unix에서 실행 가능한 쉘 스크립트를 사용할 수 없습니다. 따라서 표준화하는 것이 합리적이지 않았습니다. 사건의 상태는이 현대적인 도코로 대표됩니다.

BSD로 시작하는 파일은 #! interpreter직접 실행할 수 있지만 SysV는 a.out 파일 만 직접 실행할 수 있습니다. 즉 exec…(), BSD 프로그램에서 루틴 중 하나의 인스턴스가 SysV에서 변경되어 /bin/sh해당 프로그램에 대한 인터프리터 (일반적으로 )를 대신 실행해야 할 수도 있습니다 .
— Stephen Frede (1988). "시스템 X 릴리스 Y에서 프로그래밍". 호주 유닉스 시스템 사용자 그룹 뉴스 레터 . 권 9. 수 4. p. 111.

여기서 중요한 점은 쉘을보고있는 반면 실행 가능한 쉘 스크립트의 존재는 실제로 exec…()함수 의 문제입니다 . 쉘이하는 것은 오늘날에도 여전히 일부 쉘에서 발견되고 실행 가능한 스크립트 메커니즘 의 선구자 를 포함하고 있으며 일부 exec…p()는 오해의 소지가 있습니다. 이와 관련하여 표준에서 다루어야 exec…()할 것은 해석 된 스크립트가 작동하는 방식이며 POSIX가 처음 만들어 졌을 때 대상 운영 체제 스펙트럼의 주요 부분에서 처음에는 작동하지 않았습니다 .

부차적 인 질문은 왜 스크립트 통역사를위한 매직 넘버 메커니즘 이 우주의 AT & T 측에서 대중 에게 도달 하고 1990 년대 초에 System 5 Interface Definitionexec…() 에 문서화 되었기 때문에 이것이 표준화되지 않은 이유 입니다. :

인터프리터 파일은 다음 형식의 줄로 시작합니다

#! 경로명 [arg]
여기서 pathname 은 인터프리터의 경로이고 arg 는 선택적 인수입니다. 당신은 때 exec통역 파일, 시스템은 exec지정된 통역이야.
exec. 시스템 V 인터페이스 정의 . 1 권. 1991.

불행하게도, 행동은 오늘날 1980 년대와 같이 거의 광범위하게 존재하며 표준화해야 할 일반적인 행동은 없습니다. 일부 Unices (예 : HP-UX 및 FreeBSD)는 스크립트의 인터프리터로 스크립트를 지원하지 않습니다. 첫 줄이 공백으로 분리 된 하나, 둘 또는 많은 요소인지 여부는 MacOS (및 2005 이전의 FreeBSD 버전)와 다른 요소에 따라 다릅니다. 지원되는 최대 경로 길이가 다릅니다. POSIX 이식 가능한 파일 이름 문자 세트 이외의 문자는 선행 및 후행 공백과 같이 까다 롭습니다. 0, 1, 2 차 인수의 결과도 까다로워 시스템마다 상당한 차이가 있습니다. 현재 POSIX를 준수하지만 일부는 아닌 일부-유닉스 시스템은 여전히 ​​그러한 메커니즘을 지원하지 않으며, 명령을 지정하면 더 이상 POSIX 규격이 아닌 시스템으로 변환됩니다.

추가 자료


1

다른 답변 중 일부에서 언급했듯이 구현 방법이 다릅니다. 따라서 기존 스크립트와의 호환성 을 표준화 하고 보존 하기가 어렵습니다 . 최신 POSIX 시스템에서도 마찬가지입니다. 예를 들어, Linux는 공백으로 shebang을 완전히 토큰 화하지 않습니다. macOS에서는 스크립트 인터프리터가 다른 스크립트가 될 수 없습니다.

http://en.wikipedia.org/wiki/Shebang_(Unix)#Portability 참조

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