shebang은 스크립트를 실행하는 쉘을 결정합니까? 내가 세방을 선언하면 #!/bin/bash 의 시작 부분에서 my_shell_script.sh항상 bash를

이것은 어리석은 질문 일지 모르지만 여전히 묻습니다. 내가 세방을 선언하면

#!/bin/bash

의 시작 부분에서 my_shell_script.sh항상 bash를 사용 하여이 스크립트를 호출해야합니까

[my@comp]$bash my_shell_script.sh

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

[my@comp]$sh my_shell_script.sh

내 스크립트는 shebang을 사용하여 실행중인 쉘을 결정합니까? ksh쉘 에서도 마찬가지 입니까? AIX를 사용하고 있습니다.



답변

오두막은 #! 의 사람이 읽을 수있는 인스턴스 매직 넘버 바이트 문자열로 구성 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하는 심볼릭 링크 대시/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

답변

그렇습니다. 그건 그렇고 그것은 바보 같은 질문이 아닙니다. 내 답변에 대한 참조는 여기에 있습니다 . #으로 스크립트 시작하기!

  • 그것은 shebang 또는 “bang”라인이라고합니다.

  • Bash 인터프리터의 절대 경로 일뿐입니다.

  • 숫자 기호와 느낌표 문자 (#!)로 구성되며 / bin / bash와 같은 인터프리터의 전체 경로가 이어집니다.

    Linux의 모든 스크립트는 첫 번째 줄에 지정된 인터프리터를 사용하여 실행됩니다. 거의 모든 bash 스크립트는 종종 #! / bin / bash로 시작합니다 (Bash가 / bin에 설치되었다고 가정). 다른 쉘에서 실행되는 경우. Shebang은 Bell Laboratories의 Dennis Ritchie가 버전 7 Unix와 8 사이에서 소개했습니다. 그런 다음 버클리의 BSD 라인에도 추가되었습니다.

통역 라인 무시하기 (셰방)

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


답변

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

bash에서 할 때 :

./something

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

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

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

파일의 첫 바이트를 읽고와 비교합니다 #!.

비교가 참이면 나머지 행은 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: /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 : //.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 비록 이론적 근거 섹션에서 언급하고 있지만 “실행 가능한 스크립트가 시스템에서 지원되는 경우 발생할 수 있습니다 “.


답변

사실, 결과적으로 Shebang 행에 표시된 실행 파일은 실행 파일 일뿐입니다. 일부 텍스트 인터프리터를 실행 파일로 사용하는 것이 좋지만 반드시 그럴 필요는 없습니다. 설명과 시연을 위해 다소 쓸모없는 테스트를했습니다.

#!/bin/cat
useless text
more useless text
still more useless text

파일 이름을 test.txt로 지정하고 실행 가능 비트를 설정 chmod u+x test.txt한 다음 “호출”합니다 ./test.txt. 예상대로 파일의 내용이 출력됩니다. 이 경우 고양이는 shebang 라인을 무시하지 않습니다. 단순히 모든 라인을 출력합니다. 따라서 모든 유용한 통역사는이 shebang 라인을 무시할 수 있어야합니다. bash, perl 및 PHP의 경우 단순히 주석 줄입니다. 예, 이것들은 shebang 라인을 무시합니다.


답변

내가 수집 한 것부터 파일에 실행 가능 비트 세트가 있고 호출 될 때마다 커널은 파일 헤더를 분석하여 진행 방법을 결정합니다 (알고있는 한 LKM을 통해 사용자 정의 파일 형식에 대한 사용자 정의 처리기를 추가 할 수 있음). 파일이 #! 인 텍스트 파일 인 경우 처음에 조합하면, 실행은 다른 실행 파일 (보통 일종의 쉘)로 전달되며, 경로는 해당 shebang 바로 다음에 같은 경로로 지정됩니다. 그런 다음 커널은 셸을 실행하고 처리 할 파일을 전달합니다.

간단히 말해서 어떤 쉘을 사용하여 스크립트를 호출하든 상관 없습니다. 커널은 어느 쪽이든 적절한 방법으로 실행을 디스패치합니다.