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
따라서 스크립트는 하드코딩할 필요 없이 첫 번째 python
in을 사용합니다 . 이는 "좋은" Python 버전이 포함된 일부 시스템에서 제대로 작동할 수 있습니다.$PATH
/usr/bin/python
/usr/local/bin
/opt
내 shebang으로 "#!/path/to/NAME" 대신 "#!/usr/bin/env NAME"을 사용하는 것이 더 나은 이유는 무엇입니까?
env
Python 인터프리터( 파일에서 호출됨)가 단순히 해당 #!
행을 주석으로 처리하기 때문에 무한 루프가 생성되지 않습니다 . #!
많은 언어에서 주석 문자를 사용하기 때문에 이는 중요한 디자인 포인트입니다 #
.
이를 확장하려면,다중 언어 프로그램을 작성할 수 있습니다처음에는 아래에서 실행되지만 #!/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;
와 달리 sh
Perl 문은 개행 문자로 끝나지 않습니다.
"$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$
설명하다:
파일을 "변수"로 사용하여
\$shell_var
원하는 쉘을 정의하십시오.대시는 지원되지 않기 때문에
function f { echo hello world; }
통사론, 그래서 오류가 발생했지만function: not found
파일의 셸을 bash로 변경하면\$shell_var
더 이상 오류가 발생하지 않습니다.전체 파일 경로(또는 ./hole.sh가 /tmp에서 실행되는 경우 상대 경로)가 파일
$@
에 전달 되어 .\$shell_var
/tmp/hole.sh
\$shell_var