가변 콘텐츠를 Shebang으로 사용할 수 있나요?

가변 콘텐츠를 Shebang으로 사용할 수 있나요?

shebang을 추가하려는 쉘 스크립트가 있습니다. 다음과 같이 정의된 변수가 주어지면:

SHEBANG="#!/bin/sh"

내 질문은 다음과 같이 다른 스크립트에서 해당 변수를 사용할 수 있는지입니다.

$SHEBANG
# other stuff...

답변1

아니요. shebang 라인은 커널이나 시스템 라이브러리*에 의해 처리되며 쉘 변수는 처리하지 않습니다.

  • 어떤 이유로 환경 변수를 인터프리터로 사용하려는 경우 $SHEBANG "$@". #!이 경우 변수에서 를 생략해야 합니다 . #!문자 그대로 파일의 처음 2바이트인 경우에만 유용합니다.

  • 또 다른 옵션은shshebang 라인이 없는 스크립트는 (일반적으로) 또는 호출 쉘을 사용하여 쉘 스크립트로 실행된다는 사실. 쉘 구문과 유용하게 겹치는 shebang 대상에 대한 주석 구문이 있는 경우 이를 작동시킬 수 있습니다. 이 전략은 Lisp 인터프리터에서 일반적이거나 사용됩니다. 귀하의 예의 경우 통역사도 sh실행 가능하지 않습니다.

  • 존재한다는 사실에 의존할 수 있다면 해당 라인에서 더 많은 작업을 수행할 수 있습니다 bash. 첫 번째 라인이 다음과 같은 스크립트입니다.

    exec /bin/bash -c 'exec "$SHEBANG" <(tail -n +2 "$0")' "$0" "$@"
    

    대부분의 통역사에게 적합합니다. Bash는 중간 단계로 사용되므로프로세스 대체가지고 사용할 수 있습니다tail무한 루프에 빠지지 않도록 첫 번째 줄을 건너뛰세요. 일부 통역사는 파일을 검색할 수 있어야 하며 이와 같은 파이프라인을 허용하지 않습니다.


이것이 정말로 당신이 하고 싶은 일인지 생각해 볼 가치가 있습니다. 보안 문제를 제외하고는 그다지 유용하지 않습니다. 해석기를 그렇게 변경할 수 있는 스크립트는 거의 없으며, 가능한 경우 상황에 맞는 올바른 로직을 생성하는 보다 제한된 로직을 사용하는 것이 거의 확실히 더 나을 것입니다. (실제 스크립트에 대한 경로를 인수로 사용하여 인터프리터를 호출하는 사이의 쉘 스크립트일 수도 있습니다).


* 항상 그런 것은 아닙니다. 특정 상황에서는 일부 쉘이 스스로 읽을 수 있지만 여전히 변수 확장을 수행하지 않습니다.

답변2

이것이 당신이 염두에 두고 있는 사용 사례인지는 모르겠지만, 한 가지는 당신이~할 수 있다하는 것은

#!/usr/bin/env python

따라서 스크립트는 하드 코딩할 필요 없이 첫 번째 pythonin 을 사용합니다 . 이는 Python의 "좋은" 버전이 있는 일부 시스템에서는 제대로 작동하지 않을 수 있습니다 .$PATH/usr/bin/python/usr/local/bin/opt

내 shebang으로 "#!/path/to/NAME" 대신 "#!/usr/bin/env NAME"을 사용하는 것이 더 나은 이유는 무엇입니까?


envPython 인터프리터( 파일에서 호출)가 해당 #!행을 주석으로 처리하기 때문에 무한 루프가 생성되지 않습니다 . #!많은 언어에서 #주석 문자를 사용하기 때문에 이것이 디자인의 포인트입니다 .

이를 확장하려면,다중 언어 프로그램을 작성할 수 있습니다처음에는 에서 실행되지만 #!/bin/sh실제로 사용할 인터프리터를 파악하고 동일한 스크립트에서 이를 호출합니다.

이미 있다는 것이 밝혀졌습니다여러 줄로 된 shebang 트릭이 포함된 웹페이지컴파일된 언어를 포함한 많은 언어의 경우(스크립트는 그 자체의 일부를 컴파일러에 공급하고 출력을 실행합니다)


매뉴얼 perlrun페이지에서는 다음의 대안으로 이 예를 제공합니다 #!/usr/bin/env perl.

    #!/bin/sh
    #! -*-perl-*-
    eval 'exec perl -x -wS $0 ${1+"$@"}'
        if 0;

    your perl script goes here

/bin/sh스크립트 로 실행하면 스크립트에서 eval실행되어 인수를 전달합니다.perl -x -wS

Perl이 이를 실행하면 다음 행 eval의 가 제어되므로 if 0;결코 실행되지 않습니다. 와 달리 shPerl 문은 개행 문자로 끝나지 않습니다.

"$SHEBANG"대신에 을 사용 perl하거나 여러 sh명령을 실행하여 사용할 Perl 인터프리터를 선택하면 이를 더 복잡하게 만들 수 있습니다 .

답변3

나는 이것이 당신이 원하는 것이라고 생각합니다 :

xb@dnxb:/tmp$ cat /tmp/hole.sh
#!/usr/bin/$shell_var
echo 1
readlink "/proc/$$/exe"
echo 2
function f { echo hello world; } 
echo 3 
xb@dnxb:/tmp$ chmod +x /tmp/hole.sh
xb@dnxb:/tmp$ sudo vi /usr/bin/\$shell_var 
xb@dnxb:/tmp$ cat /usr/bin/\$shell_var 
#!/bin/bash
/bin/dash -- "$@"
xb@dnxb:/tmp$ sudo chmod +x /usr/bin/\$shell_var
xb@dnxb:/tmp$ ./hole.sh
1
/bin/dash
2
./hole.sh: 5: ./hole.sh: function: not found
3
xb@dnxb:/tmp$ sudo vi /usr/bin/\$shell_var 
xb@dnxb:/tmp$ cat /usr/bin/\$shell_var 
#!/bin/bash
/bin/bash -- "$@"
xb@dnxb:/tmp$ ./hole.sh 
1
/bin/bash
2
3
xb@dnxb:/tmp$ 

설명:

  1. 파일을 "변수"로 사용하여 \$shell_var원하는 쉘을 정의하십시오.

  2. readlink "/proc/$$/exe"현재 쉘을 인쇄합니다.

  3. 대시는 지원하지 않기 때문에function f { echo hello world; }통사론, 그래서 오류가 발생했지만 파일 function: not found에서 쉘을 bash로 변경하면 \$shell_var더 이상 오류가 발생하지 않습니다.

  4. 전체 파일 경로(또는 ./hole.sh가 /tmp에서 실행되는 경우 상대 경로)는 파일 $@로 전달되고 내부에서 실행됩니다 .\$shell_var/tmp/hole.sh\$shell_var

관련 정보