모든 쉘에서 실행될 쉘 스크립트 작성 (여러 shebang 행을 사용합니까?)


19

방금 셸 스크립팅에 대해 더 깊이 시작하기 시작했으며 항상 스크립트를 파일에 던져 표시하고 chmod +x완료 한 다음 /path/to/script.sh기본 인터프리터가 그 방법을 갖도록했습니다 .zsh라고 가정했습니다. 나는 껍질에 사용했다. 분명히 /bin/shzsh 프롬프트에서 스크립트를 실행하더라도 스크립트에 zsh 관련 항목을 넣기 시작했고 실행하지 않으면 실패하기 때문에 기본적으로있는 것 같습니다 zsh /path/to/script.sh.

요점을 알려면 다음과 같은 질문이 있습니다.

  1. #!/path/to/shell처음에 shebang 줄 ( )이 없을 때 스크립트를 실행하는 쉘은 무엇입니까? 나는 가정 /bin/sh하지만 확인할 수 없다.
  2. 모든 플랫폼에서 실행되는 쉘 스크립트 작성과 관련하여 "모범 사례"로 간주되는 것은 무엇입니까? (오케이, 이것은 일종의 개방형입니다)
  3. zsh를 사용할 수없고 zsh를 사용할 수없는 경우 bash로 폴백하는 스크립트를 작성할 수 있습니까? 아래와 같이 두 개의 shebang 줄을 넣으려고했지만 bad interpreter: /bin/zsh: no such file or directoryzsh가없는 컴퓨터에서 시도하면 오류가 발생합니다 .

    #!/bin/zsh

    #!/bin/bash

답변:


26

처음에 shebang 줄 (#! / path / to / shell)이 없을 때 스크립트를 실행하는 쉘은 무엇입니까? / bin / sh라고 가정하지만 확인할 수 없습니다.

정확한 동작은 프로그램에 따라 다릅니다 있도록 커널은 스크립트와 수익을 실행하기를 거부 ENOEXEC, 당신은 스크립트 실행 에서를 .

  • bash 4.2.39 – 자체 사용
  • busybox-ash 1.20.2 – 자체 사용
  • 대시 0.5.7 – / bin / sh 실행
  • fish 1.23.1 – ENOEXEC에 대해 불평하고 잘못된 파일을 탓합니다.
  • AT & T ksh 93u + 2012.08.01 – 자체 사용
  • mksh R40f – / bin / sh를 실행합니다
  • pdksh 5.2.14 – / bin / sh를 실행합니다
  • sh-heirloom 050706 – 자체 사용
  • tcsh 6.18.01 – / bin / sh를 실행합니다
  • zsh 5.0.0 – / bin / sh를 실행합니다
  • cmd.exe 5.1.2600 – 당신을보고 웃겨요.

에서 의 glibc , 기능 execv()또는 execve()단지 ENOEXEC를 반환합니다. 그러나이 execvp()오류 코드를 숨기고 자동으로 / bin / sh를 호출합니다. (이것은 exec (3p)에 문서화되어 있습니다.)

모든 플랫폼에서 실행되는 쉘 스크립트 작성과 관련하여 "모범 사례"로 간주되는 것은 무엇입니까? (오케이, 이것은 일종의 개방형입니다)

에 어느 스틱 sh만 POSIX 정의 기능, 또는 단지 전체 이동 배쉬 (널리 가능)하고 배포하는 경우 귀하의 요구 사항에 언급.

(이제 생각하면 Perl 또는 아마도 Python은 더 나은 구문을 갖는 것은 말할 것도없고 이식성이 훨씬 뛰어납니다.)

항상 세방 라인을 추가하십시오. bash 또는 zsh를 사용 #!/usr/bin/env bash하는 경우 쉘 경로를 하드 코딩하는 대신 사용 하십시오. (그러나 POSIX 쉘은로 보장되므로이 경우에는 /bin/sh건너 뛰십시오 env.)

불행히도, /bin/sh항상 같은 것은 아닙니다. GNU autoconf 프로그램은 여러 가지 다른 문제를 처리해야 합니다.

zsh를 사용할 수없고 zsh를 사용할 수없는 경우 bash로 폴백하는 스크립트를 작성할 수 있습니까? 아래처럼 두 개의 shebang 행을 넣으려고 시도했지만 잘못된 인터프리터에서 오류가 발생했습니다 . / bin / zsh : zsh가없는 시스템에서 시도하면 그러한 파일이나 디렉토리가 없습니다 .

셰방 라인은 하나만있을 수 있습니다. 개행 문자 뒤의 모든 것은 커널에 의해 읽히지 않고 쉘에 의한 주석으로 취급됩니다.

그건 가능한 실행으로하는 스크립트를 작성하는 #!/bin/sh쉘을 사용할 수를 확인하고, 실행, exec zsh "$0" "$@"또는 exec bash "$0" "$@"그 결과에 따라. 그러나 bash와 zsh가 사용하는 구문은 여러 곳에서 매우 다르므로 자신의 정신을 위해 이것을 권장하지 않습니다 .


1
ENOEXEC를 받았을 때 각 쉘이 실제로 호출 한 것을 어떻게 추적 했습니까?
swrobel

2
@SWrobel : 사용 strace -f -e fork,clone,execve. /bin/sh실패 후 일부 포탄은 집행에 갔다 ; 다른 사람들은 대본 자체를 해석했습니다.
grawity

1
@SWrobel : 또 다른 방법은로 구성된 스크립트를 실행하는 것입니다 readlink /proc/$$/exe.
grawity


1
들어 cshtcsh스크립트로 시작 여부에 관계없이 동작에 따라 달라집니다 #(자신 대신 쉬 호출하는 경우 그들은에서 스크립트를 해석하는). 그것은 csh가 주석을 지원했지만 Bourne 쉘은 지원하지 않는 시간으로 돌아 갔으므로 a #는 csh 스크립트라는 힌트였습니다.
sch

2

1) 현재 실행중인 쉘. (어떤 쉘이든)

2) 동일한 쉘 유형 (bash / dash / ash / csh / 맛에 관계없이)을 사용하고 "지원되는 플랫폼"이 기본적으로 사용하려는 쉘을 설치하는지 확인하십시오. 또한 시스템에서 일반적으로 사용 가능한 명령을 사용하십시오. 기계 별 옵션을 피하십시오.

3) 실제로 "if-then-else"논리는 없습니다 interpreter directive. 지원하려는 모든 시스템에 존재해야하는 쉘을 지정해야합니다. 즉 #!/bin/bash, #!/bin/sh스크립트가 모든 쉘에서 상당히 일반적인 경우 에는 제네릭 을 지정 하십시오.

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