Shebang은 스크립트가 실행되는 쉘을 결정합니까?

Shebang은 스크립트가 실행되는 쉘을 결정합니까?

어리석은 질문일지도 모르지만, 그래도 물어보겠습니다. 내가 셰뱅을 선언한다면

#!/bin/bash 

그래서 항상 my_shell_script.shbash를 사용하여 이 스크립트를 호출해야 합니다.

[my@comp]$bash my_shell_script.sh

또는 예를 들어 사용할 수 있습니다.

[my@comp]$sh my_shell_script.sh

내 스크립트는 shebang을 사용하여 어떤 쉘이 실행되고 있는지 확인합니까? 쉘에서도 같은 일이 발생합니까 ksh? 저는 AIX를 사용하고 있습니다.

답변1

이것셰르본 #!사람이 읽을 수 있는 인스턴스입니다.매직넘버실행할 파일이 스크립트인지 바이너리 파일인지 확인하기 위해 0x23 0x21함수 계열에서 사용하는 바이트 문자열로 구성됩니다 . exec()Shebang이 존재하는 경우 exec()Shebang 이후에 지정된 실행 파일이 실행됩니다.

이는 다음과 같이 명령줄에서 인터프리터를 지정하여 스크립트를 호출하는 경우를 의미합니다.둘 다질문에 주어진 상황은 exec()명령줄에 지정된 인터프리터를 실행하며 스크립트를 보지도 않습니다.

exec()따라서 다른 사람들이 지적했듯이 shebang 라인에 지정된 인터프리터를 호출 하려면 스크립트가 실행 가능 비트를 설정하고 다음과 같이 호출되어야 합니다 ./my_shell_script.sh.

이 동작은 다음 스크립트를 사용하여 쉽게 시연됩니다.

#!/bin/ksh
readlink /proc/$$/exe

설명하다:

  • #!/bin/kshksh통역사로 정의됩니다 .

  • $$현재 프로세스의 PID를 저장합니다.

  • /proc/pid/exe프로세스 실행 파일에 대한 심볼릭 링크입니다(적어도 Linux에서는 AIX에서 /proc/$$/object/a.out은 실행 파일에 대한 링크입니다).

  • readlink심볼릭 링크의 값을 출력합니다.

예:

노트: 기본 쉘이 /bin/sh심볼릭 링크인 Ubuntu에서 이것을 시연했습니다.스프린트즉, 심볼릭 링크 /bin/dash와 심볼릭 링크입니다./bin/ksh/etc/alternatives/ksh/bin/pdksh

$ chmod +x getshell.sh
$ ./getshell.sh 
/bin/pdksh
$ bash getshell.sh 
/bin/bash
$ sh getshell.sh 
/bin/dash

답변2

네, 그렇습니다. 그건 그렇고, 이것은 어리석은 질문이 아닙니다. 내 답변에 대한 참조는 다음과 같습니다.여기. #으로 스크립트를 시작하세요!

  • 이를 shebang 또는 "bang" 라인이라고 합니다.

  • Bash 인터프리터의 절대 경로에 지나지 않습니다.

  • 이는 숫자 기호와 느낌표 문자(#!), 그 뒤에 통역사에 대한 전체 경로(예: /bin/bash)로 구성됩니다.

    Linux의 모든 스크립트는 첫 번째 줄에 지정된 인터프리터를 사용하여 실행됩니다. 거의 모든 bash 스크립트는 일반적으로 #!/bin/bash로 시작합니다(Bash가 /bin에 설치되어 있다고 가정). 다른 쉘에서 실행되는 경우에도 마찬가지입니다. Shebang은 Bell Labs의 Unix 버전 7과 8 사이에 Dennis Ritchie에 의해 도입되었습니다. 그런 다음 Berkeley BSD 제품군에도 추가되었습니다.

통역사 라인 무시(shebang)

인터프리터 라인이 지정되지 않은 경우 기본값은 일반적으로 /bin/sh입니다. 그러나 #!/bin/bash 라인을 설정하는 것이 좋습니다.

답변3

execLinux 커널의 시스템 호출은 기본적으로 shebang을 이해합니다( #!).

나는 OP가 AIX에 대해 묻는 것을 보지 못했습니다. Linux에 대해 내가 아는 것을 말하고 거기에 강력한 비유가 있을 것이라고 확신하거나 적어도 Linux를 찾는 대부분의 Google 직원을 만족시킬 것입니다 :-)

Bash에서 다음을 수행할 때:

./something

Linux에서는 execpath 를 사용하여 시스템 호출을 호출 합니다 ./something.

다음 커널 행은 다음으로 전달된 파일에서 호출됩니다 exec.https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25

if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))

파일의 첫 번째 바이트를 읽고 이를 #!.

비교가 true이면 나머지 줄은 Linux 커널에 의해 구문 분석되고 exec경로 /usr/bin/env python와 현재 파일을 첫 번째 인수로 사용하여 또 다른 호출이 이루어집니다.

/usr/bin/env python /path/to/script.py

이는 #주석 문자로 사용되는 모든 스크립트 언어에 적용됩니다.

예, 다음을 사용하여 무한 루프를 만들 수 있습니다.

printf '#!/a\n' | sudo tee /a
sudo chmod +x /a
/a

Bash는 오류를 인식했습니다.

-bash: /a: /a: bad interpreter: Too many levels of symbolic links

#!사람이 읽을 수 있지만 필수는 아닙니다.

파일이 다른 바이트로 시작하면 exec시스템 호출은 다른 처리기를 사용합니다. 또 다른 가장 중요한 내장 핸들러는 ELF 실행 파일용입니다:https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305바이트를 확인합니다 7f 45 4c 46(사람이 읽을 수도 있음 .ELF). /bin/lsELF 실행 파일인 처음 4바이트를 읽어 이를 확인해 보겠습니다 .

head -c 4 "$(which ls)" | hd 

산출:

00000000  7f 45 4c 46                                       |.ELF|
00000004                                                                 

따라서 커널은 이러한 바이트를 볼 때 ELF 파일을 가져와 메모리에 올바르게 저장하고 이를 사용하여 새 프로세스를 시작합니다. 또한보십시오:https://stackoverflow.com/questions/8352535/how-does-kernel-get-an-executable-binary-file-running-under-linux/31394861#31394861

마지막으로 이 binfmt_misc메커니즘을 사용하여 자신만의 shebang 핸들러를 추가할 수 있습니다. 예를 들어 다음을 추가할 수 있습니다..jar파일에 대한 사용자 정의 핸들러. 이 메커니즘은 파일 확장자별 처리도 지원합니다. 또 다른 응용 프로그램은QEMU를 사용하여 다양한 아키텍처의 실행 파일을 투명하게 실행.

그러나 POSIX가 shebang을 지정하지 않는다고 생각합니다.https://unix.stackexchange.com/a/346214/32558, 이론적 근거 섹션에서 이에 대해 언급하고 있지만 "시스템이 실행 가능한 스크립트를 지원하면 어떤 일이 발생할 수 있습니다"라는 형식으로 표시됩니다.

답변4

내가 수집한 것에서 파일에 실행 가능 비트가 설정되어 있고 호출될 때마다 커널은 파일 헤더를 구문 분석하여 진행 방법을 결정합니다(내가 아는 한 LKM을 통해 사용자 정의 파일 형식에 대한 사용자 정의 핸들러를 추가할 수 있음). 파일이 시작 부분에 #!이 있는 텍스트 파일 조합으로 나타나면 해당 실행은 지정된 동일한 줄에서 해당 shebang 바로 뒤에 경로가 있는 다른 실행 파일(일반적으로 일종의 셸)로 전달됩니다. 그런 다음 커널은 셸을 실행하고 처리를 위해 파일을 전달합니다.

간단히 말해서, 스크립트를 호출하는 데 어떤 쉘이 사용되는지는 중요하지 않습니다. 어느 쪽이든 커널은 실행을 적절한 쉘로 전달합니다.

관련 정보