쉘 스크립트 헤더 (#! / bin / sh 대 #! / bin / csh)


92

모든 스크립트 파일이

#!/bin/sh

또는

#!/bin/csh

그게 필요합니까? 이것의 목적은 무엇입니까? 그리고 둘의 차이점은 무엇입니까?


1
csh 스크립트의 경우 #!/bin/csh -f; 는 -f소스하지 쉘을 알려주는 사용자 .login.cshrc빠른 스크립트 실행을하고 사용자의 설정에 대한 종속성을 피한다. (또는 더 좋은 방법은 csh 스크립트를 작성하지 않는 것 -f입니다 .) sh 또는 bash 스크립트 에는 사용하지 마십시오 . 같은 의미가 아닙니다.
Keith Thompson

답변:


99

이것은 다음과 같이 알려져 있습니다 Shebang.

http://en.wikipedia.org/wiki/Shebang_(Unix)

#! interpreter [optional-arg]

shebang은 스크립트에 실행 권한이있는 경우에만 관련됩니다 (예 : chmod u + x script.sh).

쉘이 스크립트를 실행할 때 지정된 인터프리터를 사용합니다.

예:

#!/bin/bash
# file: foo.sh
echo 1

$ chmod u+x foo.sh
$ ./foo.sh
  1

@Kolob Canyon은 필요하지 않지만 구문 강조 기능으로 일부 편집자에게 도움이 될 수 있습니다 (일반적으로 동일한 작업을 수행하는 다른 방법이 있지만) : unix.stackexchange.com/a/88730/193985
Braham Snyder

42

#!줄은 커널 (특히 execve시스템 호출 의 구현 )에이 프로그램이 해석 된 언어로 작성되었음을 알려줍니다 . 다음에 오는 절대 경로 이름은 인터프리터를 식별합니다. 기계어 코드로 컴파일 된 프로그램은 대부분의 최신 Unix에서 7f 45 4c 46( ^?ELF) 다른 바이트 시퀀스로 시작하여 이를 식별합니다.

프로그램 자체가 스크립트 가 아닌 한 , 뒤에 원하는 프로그램 에 대한 절대 경로를 넣을 수 있습니다 . 커널은 다음 호출을 다시 작성합니다.#!#!

./script arg1 arg2 arg3 ...

명령 줄이 실제로 있었던 것처럼 ./script시작하는 곳 은#! /usr/bin/perl

/usr/bin/perl ./script arg1 arg2 arg3

또는 #! /bin/sh이미 살펴본 것처럼를 사용하여에서 해석 할 스크립트를 작성할 수 있습니다 sh.

#!줄은 명령 줄 에서 스크립트 를 직접 호출하는 경우에만 처리됩니다 ./script. 파일도 실행 가능해야합니다 ( chmod +x script). 그렇게 sh ./script하면 #!라인이 필요하지 않으며 (존재하는 경우 무시 됨) 파일이 실행 가능하지 않아도됩니다. 포인트 기능의 그들이에 기록 된 어떤 언어 몰라도 해석 언어 프로그램 된 invoke 직접 당신을 허용하는 것입니다. (음주 grep '^#!' /usr/bin/*- 당신은 수많은 재고 프로그램이이 기능을 사용하여 사실에 있음을 발견 할 것입니다.)

이 기능을 사용하기위한 몇 가지 규칙은 다음과 같습니다.

  • #!맨 처음이해야 바이트 파일입니다. 특히 파일 ASCII 호환 인코딩 (예 : UTF-8은 작동하지만 UTF-16은 작동하지 않음) 이어야 하며 "바이트 순서 표시"로 시작 해서는 안됩니다. 그렇지 않으면 커널이이를 인식하지 못합니다. #!스크립트.
  • 뒤의 경로 #!는 절대 경로 여야합니다 (로 시작 /). 공백, 탭 또는 개행 문자를 포함 할 수 없습니다.
  • #!와 사이에 공백을 두는 것은 좋은 스타일이지만 필수는 아닙니다 /. 여기에 두 개 이상의 공간을 두지 마십시오.
  • #!줄 에 셸 변수를 넣을 수 없으며 확장되지 않습니다.
  • 하나의 공백으로 구분하여 절대 경로 뒤에 하나의 명령 줄 인수를 넣을 수 있습니다 . 절대 경로와 마찬가지로이 인수는 공백, 탭 또는 개행 문자를 포함 할 수 없습니다. 때로는 작업을 수행하는 데 필요하고 ( #! /usr/bin/awk -f) 때로는 유용합니다 ( #! /usr/bin/perl -Tw). 불행히도 절대 경로 뒤에 개 이상의 인수를 넣을 수 없습니다 .
  • 어떤 사람들은 #! /usr/bin/env interpreter대신 을 사용하라고 말할 것입니다 #! /absolute/path/to/interpreter. 이것은 거의 항상 실수입니다. 프로그램의 동작은 $PATH스크립트를 호출하는 사용자 의 변수에 따라 달라집니다 . 그리고 모든 시스템이 env애초에 그런 것은 아닙니다 .
  • 필요 setuid하거나 setgid권한이없는 프로그램은 사용할 수 없습니다 #!. 기계 코드로 컴파일해야합니다. (무엇인지 모르더라도 setuid걱정하지 마십시오.)

에 관해서 는 Nutrimat Advanced Tea Substitute차에하는 것과 대략적으로 csh관련이 있습니다. 대화식 사용 에 비해 많은 이점 이 있지만 (또는 그보다 최근의 구현 이 따라 잡았 지만 ) 스크립팅에 사용하는 것은 거의 항상 실수 입니다. 일반적으로 셸 스크립팅을 처음 사용하는 경우 무시하고 . 친척을 로그인 셸로 사용하는 경우 또는로 전환 하여 대화 형 명령 언어가 학습중인 스크립팅 언어와 동일하도록합니다.shshshtcshshcshbashzsh


최신 버전의 Linux에서는 지정된 인터프리터가 스크립트가 될 수 있습니다. 뒤에 공백을 생략하는 것이 일반적입니다 #!. 좋은 스타일인지에 대해서는 언급하지 않습니다. 해킹 의 장단점에 대한 토론은 이 질문내 대답 을 참조하십시오 #!/usr/bin/env.
Keith Thompson

@KeithThompson Linux는 인터프리터가 스크립트가 될 수 있는 유일한 일반적인 Unix 변형이므로 여전히 의존 할 것이 아닙니다. 내가이 글을 쓴 이후로 나 자신 #!/usr/bin/env이 옳은 일이었던 상황에 직면 했지만 거의 항상 나쁜 생각이라고 생각합니다.
zwol 2015 년

4

이것은 스크립트를 해석 / 실행하기 위해 사용하는 쉘 (명령 인터프리터)을 정의합니다. 각 셸은 사용자와 상호 작용하고 스크립트 (프로그램)를 실행하는 방식이 약간 다릅니다.

Unix 프롬프트에서 명령을 입력하면 쉘과 상호 작용하게됩니다.

#!/bin/csh를 들어 C- 쉘, /bin/tcsht- 쉘, /bin/bashbash 쉘 등을 나타냅니다 .

어떤 대화 형 셸을 사용하고 있는지 알 수 있습니다.

 echo $SHELL

명령 또는 대안으로

 env | grep -i shell

명령을 사용하여 명령 셸을 변경할 수 있습니다 chsh.

각각은 약간 다른 명령 집합과 변수 할당 방법 및 자체 프로그래밍 구성 집합을 가지고 있습니다. 예를 들어 bash를 사용하는 if-else 문은 C- 셸에있는 문과 다르게 보입니다.

이 페이지 는 bash와 tcsh 명령 / 구문을 "번역"하므로 흥미로울 수 있습니다.

쉘 스크립트에서 지시문을 사용하면 다른 쉘을 사용하여 프로그램을 실행할 수 있습니다. 예를 들어 tcsh셸을 대화식으로 사용하지만 종종 스크립트 파일에서 / bin / bash를 사용하여 bash 스크립트를 실행합니다.

곁에:

이 개념은 다른 스크립트에도 적용됩니다. 예를 들어 Python으로 프로그래밍하면

 #!/usr/bin/python

Python 프로그램 맨 위에


그래서 필요합니까? 내가 실제로 사용하고있는 셸을 어떻게 알 수 있습니까?
One Two Three

따라서 누군가가 자신의 컴퓨터에서 사용할 수있는 스크립트를 작성하고 있는데 그들이 어떤 셸을 사용하고 있는지 모르겠습니다. (불행히도이 사람은이 일에 대해 단서가 없으므로 그가 할 수있는 일은 아무것도 변경하지 않고 스크립트를 실행하는 것뿐입니다). 다음과 같이 할 수 있습니까 #! $SHELL? 이것이 Shebang에 올바른 쉘을 넣을까요?
One Two Three

1
@OneTwoThree 대부분의 시스템에는 표준 셸이 있으며 bash 또는 csh 스크립트를 작성하면 괜찮습니다. 그들이 대화식으로 사용하는 쉘은 중요 하지 않습니다!#/bin/bash . 그것은 eg, 지시문 의 아름다움입니다 . 쉘 스크립트를 실행하기 위해 사용할 쉘을 시스템에 알려줍니다.
Levon

의 값 $SHELL이 현재 실행중인 셸을 반드시 알려주 는 것은 아닙니다. 일반적으로 기본 셸을 알려줍니다 . tcsh 세트 $version$tcsh; bash 세트 $BASH_VERSION. 모든 쉘이 반드시 유사한 메커니즘을 가지고있는 것은 아닙니다.
Keith Thompson

1
@OneTwoThree :이 #!줄은 스크립트 를 실행하는 사람이 사용하는 대화 형 셸이 아니라 스크립트 구문과 일치해야합니다 .
Keith Thompson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.