shebang을 추가하려는 쉘 스크립트가 있습니다. 다음과 같이 정의된 변수가 주어지면:
SHEBANG="#!/bin/sh"
내 질문은 다음과 같이 다른 스크립트에서 해당 변수를 사용할 수 있는지입니다.
$SHEBANG
# other stuff...
답변1
아니요. shebang 라인은 커널이나 시스템 라이브러리*에 의해 처리되며 쉘 변수는 처리하지 않습니다.
어떤 이유로 환경 변수를 인터프리터로 사용하려는 경우
$SHEBANG "$@"
.#!
이 경우 변수에서 를 생략해야 합니다 .#!
문자 그대로 파일의 처음 2바이트인 경우에만 유용합니다.또 다른 옵션은
sh
shebang 라인이 없는 스크립트는 (일반적으로) 또는 호출 쉘을 사용하여 쉘 스크립트로 실행된다는 사실. 쉘 구문과 유용하게 겹치는 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