에서 bash
또는 sh
, 나는 시작 아무것도 추측 #
A는 코멘트를 .
그러나 bash
스크립트에서 우리는 다음과 같이 씁니다.
#!/bin/bash
그리고 파이썬 스크립트에는 다음이 있습니다.
#!/bin/python
이것은 #
그 자체로는 주석이지만 #!
그렇지 않은 것을 의미합니까 ?
에서 bash
또는 sh
, 나는 시작 아무것도 추측 #
A는 코멘트를 .
그러나 bash
스크립트에서 우리는 다음과 같이 씁니다.
#!/bin/bash
그리고 파이썬 스크립트에는 다음이 있습니다.
#!/bin/python
이것은 #
그 자체로는 주석이지만 #!
그렇지 않은 것을 의미합니까 ?
답변:
#!
줄은 스크립트가 실행 되기 전에 사용 된 다음 스크립트가 실행될 때 무시 됩니다.당신은 shebang 라인 과 일반적인 주석 의 차이점이 무엇인지 묻습니다 .
로 시작하는 행은로 시작 #!
하는 다른 행과 마찬가지로 주석입니다 #
. 이 #!
파일의 첫 번째 줄이거 나 다른 곳인 경우에도 마찬가지입니다. #!/bin/sh
영향 을 주지만 , 인터프리터 자체는 읽지 않습니다 .
#
는 모든 프로그래밍 언어의 주석은 아니지만, 아시다시피, sh
및 bash
( 및 대부분의 Bourne 스타일이 아닌 쉘과 같은 csh
) Bourne 스타일 쉘의 주석입니다 . 또한 파이썬의 주석이기도합니다 . 그리고 실제로 스크립트가 아닌 다양한 구성 파일의 주석입니다 (예 /etc/fstab
:).
쉘 스크립트가로 시작한다고 가정하십시오 #!/bin/sh
. 그것은 주석이며, 인터프리터 (쉘)는 #
문자 뒤의 줄에있는 모든 것을 무시 합니다.
#!
라인 의 목적은 통역사에게 정보를 제공 하는 것이 아닙니다. #!
라인 의 목적은 운영 체제 (또는 인터프리터를 시작하는 모든 프로세스) 에게 인터프리터 로 사용할 것을 알려주는 것 입니다.
예를 들어을 실행하여 스크립트를 실행 파일로 호출하면 ./script.sh
시스템은 첫 번째 행을 참조하여로 시작하는지 #!
, 공백이 0 개 이상인지, 명령 이 있는지 확인합니다 . 그럴 경우 스크립트 이름을 인수로 사용하여 해당 명령을 실행합니다. 이 예에서는 /bin/sh script.sh
(또는 기술적으로 /bin/sh ./script.sh
) 실행됩니다 .
인터프리터를 명시 적으로 호출하여 스크립트를 호출하면 #!
라인이 참조되지 않습니다. 따라서을 실행 sh script.sh
하면 첫 번째 줄은 효과가 없습니다. 경우 script2.sh
의 첫 번째 줄은 #!/usr/games/nibbles
, 달리기 sh script2.sh
에서 스크립트를 열려고하지 않을 것이다 nibbles
(하지만 ./script2.sh
것입니다).
두 경우 모두 스크립트의 확장 ( .sh
)이 있으면 실행 방법에 영향을 미치지 않습니다. 유닉스 계열 시스템에서는 일반적으로 스크립트 실행 방법에 영향을 미치지 않습니다. Windows와 같은 다른 시스템에서는 #!
shebang 행이 시스템에서 완전히 무시 될 수 있으며 확장 프로그램에서 스크립트를 실행할 항목을 결정할 수 있습니다. (이것은 스크립트 확장명을 제공 할 필요는 없지만, 그렇게하면 스크립트가 올바른 이유 중 하나입니다.)
#!
주석을 시작 하기 때문에이 목적을 정확하게 수행하도록 선택되었습니다 #
. 이 #!
줄은 통역사가 아닌 시스템을위한 것이며 통역사가 무시해야합니다.
당신은 (원래) 사용했다 #!/bin/sh
위한 bash
스크립트. 스크립트에 bash
확장자 sh
가 필요하지 않은 경우에만 스크립트 를 실행할 수 있어야합니다. sh
항상에 대한 심볼릭 링크는 아닙니다 bash
. 종종 포함한 모든 원격 최근 데비안과 우분투 시스템 , sh
에 심볼릭 링크입니다 dash
.
또한 (편집하기 전에 질문의 첫 번째 버전에서)로 Python 스크립트를 시작한다고 말했습니다 #!/bin/sh read by the interpretor
. 당신이 말 그대로 그 의미라면, 그 일을 중단해야합니다. hello.py
해당 줄로 시작 하면 running ./hello.py
은 다음을 실행합니다.
/bin/sh read by the interpretor hello.py
/bin/sh
는 read
( by the interpretor hello.py
인수 와 함께) 라는 스크립트를 실행하려고 시도하며 , read
희망적으로는 찾을 수 없으며 Python 인터프리터는 Python 스크립트를 볼 수 없습니다.
이 실수를하고 있지만 내가 설명하는 문제가 없다면, 인터프리터 (예 :)를 명시 적으로 지정 python hello.py
하여 첫 번째 줄이 무시되도록 파이썬 스크립을 호출했을 것입니다 . 스크립트를 다른 사람에게 배포하거나 나중에 오래 사용하면 스크립트가 작동하는 데 필요한지 확실하지 않을 수 있습니다. 지금 수정하는 것이 가장 좋습니다. 또는 적어도 첫 번째 줄을 완전히 제거 ./
하면 오류 메시지 와 함께 실행되지 않을 때 의미가 있습니다.
파이썬 스크립트의 경우, 파이썬 인터프리터가 어디에 있는지 (혹은 앞으로 있을지) 알면 #!
같은 방식으로 줄을 작성할 수 있습니다 .
#!/usr/bin/python
그것은 파이썬 3 스크립트가 있는지 또는, 당신은 지정해야 python3
하기 때문에, python
거의 항상 파이썬 2 :
#!/usr/bin/python3
그러나 문제는 /bin/sh
항상 존재해야 하며 OS와 함께 제공 /bin/bash
되는 시스템에는 거의 항상 존재한다는 bash
것입니다. 파이썬은 다양한 장소에 존재할 수 있습니다.
따라서 많은 파이썬 프로그래머는 이것을 대신 사용합니다.
#!/usr/bin/env python
(또는 #!/usr/bin/env python3
Python 3의 경우)
이렇게하면 스크립트 env
가 올바른 위치에 의존하는 대신 "적절한 위치"에 의존하게됩니다 python
. 다음과 같은 이유로 좋은 것입니다.
env
거의 항상에 있습니다 /usr/bin
.python
해야하는 것은 시스템에서 가장 먼저 나타나는 것 PATH
입니다. make run으로 시작 hello.py
하는 (가상) running과 같습니다 .#!/usr/bin/env python
./hello.py
/usr/bin/env python hello.py
python hello.py
사용할 수없는 이유 #!python
는 다음과 같습니다.
/
) 로 제공되기를 원합니다 .python
현재 디렉토리에서 실행 됩니다 . 명령에 슬래시가 포함되지 않은 경우 경로를 검색하는 것은 특정 쉘 동작입니다.때때로 쉘 스크립트가 아닌 Python 또는 기타 스크립트 는 다른 코드가 있는 #!/bin/sh ...
곳에서 시작되는 shebang 줄을 갖습니다 ...
. sh
파이썬 인터프리터를 호출하기 위해 인수와 함께 Bourne 호환 쉘 ( ) 을 호출하는 방법이 있기 때문에 때때로 올바른 것입니다. (인수 중 하나에 아마도을 포함 할 것입니다 python
.) 그러나 대부분의 #!/usr/bin/env python
경우 단순하고 우아하며 원하는 방식으로 작동 할 가능성이 높습니다.
많은 프로그래밍 및 스크립팅 언어 및 기타 파일 형식 #
이 주석으로 사용 됩니다. 이들 중 하나의 경우, 첫 번째 행에 프로그램을 지정하여 파일을 인수로 사용하는 프로그램이 언어로 된 파일을 실행할 수 있습니다 #!
.
일부 프로그래밍 언어에서 #
일반적으로 주석은 아니지만 특수한 경우 첫 줄은로 시작하면 무시됩니다 #!
. 주석 을 #!
달지 않아도 구문을 쉽게 사용할 수 있습니다 #
.
직관적이지 않지만 파일 형식이 첫 번째 줄부터 시작 #!
하여 실행 파일의 전체 경로를 수용 할 수있는 파일은 shebang 줄을 가질 수 있습니다. 이 작업을 수행하고 파일이 실행 가능으로 표시되면 파일처럼 문서처럼 열리도록 프로그램처럼 실행할 수 있습니다.
일부 응용 프로그램은이 동작을 의도적으로 사용합니다. 예를 들어, VMware에서 .vmx
파일은 가상 머신을 정의합니다. 가상 머신은 스크립트처럼 가상 머신을 "실행"할 수 있습니다. 이러한 파일은 실행 가능으로 표시되어 있으며 가상 머신이 VMware 유틸리티에서 열립니다.
rm
파일을 제거합니다. 스크립트 언어가 아닙니다. 그러나 #!/bin/rm
실행 파일로 시작 하고 표시된 파일을 실행할 수 있으며 실행할 때 파일을 rm
호출하여 삭제합니다.
이것은 종종 "파일 자체 삭제"로 개념화됩니다. 그러나 파일이 실제로 실행되고 있지 않습니다. 이것은 .vmx
파일에 대해 위에서 설명한 상황과 비슷 합니다.
이 #!
행은 간단한 명령 (명령 줄 인수 포함)의 실행을 용이하게하기 때문에 이런 식으로 일부 스크립팅을 수행 할 수 있습니다. 보다 복잡한 "스크립트"의 간단한 예로 다음을 #!/bin/rm
고려하십시오.
#!/usr/bin/env tee -a
이것은 사용자 입력을 대화식으로 가져 와서 한 줄씩 다시 에코하여 "스크립트"파일의 끝에 추가합니다.
유능한? 하지 매우. 개념적으로 흥미로운가요? 전적으로! 예. (약간.)
예를 들어, 언어 가없는 OS에서 hashbang 기능을 시뮬레이트하기 위한 한 번에 여러 언어 인 스크립트 / 프로그램 .
(이러한 프로그램을 폴리 글로 트라고 하지만 소프트웨어 개발 에서 다른 부분 의 폴리 글 로트 와 혼동되어서는 안됩니다 . 다른 부분은 다른 언어로 작성된 프로그램 / 프로젝트입니다.)
QBasic / QuickBASIC의 메타 명령 은 코드 생성을위한 컴파일러 (컴파일 된 코드 용) 옵션에 신호를 주지만 주석의 일부이므로 실제 컴파일 / 해석 중에 무시됩니다.
-x
플래그는 무엇을합니까?
-x
"[S] 첫 번째 줄 ... 스킵"제 2 라인은 번호가됩니다 1
대신 2
, 3 라인 2
대신을 3
당신이 플래그를 사용하지 말아야하는 이유이다 등. ;) -x
은 shebang과 같은 구문으로 시작하지 않는 Unix와 같은 OS가 아닌 스크립트에서 작성합니다 #
(따라서 Python 주석이 아님).
perl script.pl
vs ./script.pl
) 인터프리터 는 shebang 행을 읽고와 같은 플래그를 구문 분석합니다 -w
. 그래도이 기능에 의존하지 않는 것이 좋습니다.
shebang은 스크립트의 첫 줄에서 처음 두 문자로 나타날 때 문자 번호 부호와 느낌표 (예 : "#!")로 구성된 문자 순서입니다.
* nix 운영 체제에서 shebang으로 시작하는 스크립트가 실행될 때 프로그램 로더는 나머지 스크립트의 초기 행을 해석기 지시문으로 구문 분석합니다. 지정된 인터프리터 프로그램이 대신 실행되어 스크립트를 실행할 때 처음에 사용 된 경로를 인수로 전달합니다. 예를 들어, 스크립트 이름이 "path / to / your-script"경로로 지정되고 다음 줄로 시작하는 경우 :
#!/bin/sh
프로그램 로더는 "path / to / your-script"를 첫 번째 인자로 전달하는 대신 Bourne 쉘 또는 호환 쉘과 같이 "/ bin / sh"프로그램을 실행하라는 지시를받습니다.
따라서 스크립트는 "path / to / python-script"경로로 이름이 지정되며 다음 줄로 시작합니다.
#!/bin/python
로드 된 프로그램은 "path / to / python-script"를 첫 번째 인수로 전달하는 대신 파이썬 인터프리터와 같이 프로그램 "/ bin / python"을 실행하도록 지시됩니다.
간단히 말해서 "#"은 문자 순서 "#!"동안 줄을 주석 처리합니다. 스크립트의 첫 줄에서 처음 두 문자로 나타나는 것은 위와 같은 의미를 갖습니다.
자세한 내용은 일부 스크립트가 #으로 시작하는 이유 를 참조하십시오 . ...?
출처 : 이 답변의 일부 섹션에서 (약간의 수정과 함께) 파생 오두막 (유닉스) 에서 영어 위키 백과 (가 위키 백과 기여자 ). 이 문서는 AU의 사용자 콘텐츠와 동일하게 CC-BY-SA 3.0 에 따라 사용이 허가되므로이 파생물은 저작자 표시가 허용됩니다.
#!
shebang
스크립트의 첫 줄에 처음 두 문자로 나타날 때를 호출합니다 . 스크립트에서 실행을위한 인터프리터를 나타내는 데 사용됩니다. 은 shebang
하지 쉘의 운영 체제 (커널)입니다; 주석으로 해석되지 않습니다.
예의 : http://en.wikipedia.org/wiki/Shebang_%28Unix%29
일반적으로 파일이 실행 가능하지만 실제로는 실행 가능 (이진) 프로그램이 아니고 해당 행이있는 경우 프로그램은 #! 스크립트 이름과 모든 인수로 시작됩니다. 이 두 문자 #와! 파일에서 처음 2 바이트 여야합니다!
자세한 정보 : http://wiki.bash-hackers.org/scripting/basics#the_shebang
아니요, exec
Linux 커널 의 시스템 호출 에서만 사용되며 인터프리터의 주석으로 처리됩니다.
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/ls
ELF 실행 파일 인의 첫 번째 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 비록 이론적 근거 섹션에 언급되어 있지만 "실행 가능한 스크립트가 시스템에서 지원되는 경우 우연히 있다".
#include
. 거기에도 역시#
주석이 아닙니다.