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

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

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

SHEBANG="#!/bin/sh"

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

$SHEBANG
# other stuff...

답변1

습관. Shebang 라인은 커널 또는 시스템 라이브러리*에 의해 처리되며 쉘 변수를 처리하지 않습니다.

  • 어떤 이유로 환경 변수를 인터프리터로 사용하려는 경우 재생성된 "트램펄린" 실행 파일(스크립트 아님!)을 만들 수 있습니다 $SHEBANG "$@". 이 경우 #!변수에서 를 생략해야 합니다 . #!실제로 파일의 처음 2바이트인 경우에만 도움이 됩니다.

  • 또 다른 옵션은 다음을 활용하는 것입니다.실제로 shebang 라인이 없는 스크립트는 (보통) sh호출 쉘과 함께 쉘 스크립트로 실행됩니다.. 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

관련 정보