스크립트가 시작된 후 hashbang의 if/else와 같은 해석기를 선택합니다.

스크립트가 시작된 후 hashbang의 if/else와 같은 해석기를 선택합니다.

스크립트를 실행하는 인터프리터를 동적으로 선택하는 방법이 있습니까? 서로 다른 두 시스템에서 실행되는 스크립트가 있는데 사용하려는 인터프리터가 두 시스템의 서로 다른 위치에 있습니다. 결국 내가 해야 할 일은 전환할 때마다 해시뱅 라인을 변경하는 것이었습니다. 내가 하고 싶은 일은논리이것과 동일합니다(이와 같은 정확한 구성이 불가능하다는 것을 알고 있습니다):

if running on system A:
    #!/path/to/python/on/systemA
elif running on system B:
    #!/path/on/systemB

#Rest of script goes here

또는 첫 번째 인터프리터를 사용하려고 시도하고 찾을 수 없으면 두 번째 인터프리터를 사용하는 것이 더 좋습니다.

try:
    #!/path/to/python/on/systemA
except: 
    #!path/on/systemB

#Rest of script goes here

분명히 내가 어디에 있는지에 따라 그렇게 할 수 있지만 실제로 /path/to/python/on/systemA myscript.py 실행 /path/on/systemB myscript.py 되는 래퍼 스크립트가 있으므로 myscript.py수동이 아닌 프로그래밍 방식으로 Python 인터프리터에 대한 경로를 지정하고 싶습니다.

답변1

실제 프로그램에 대한 올바른 인터프리터를 찾기 위해 언제든지 래퍼 스크립트를 만들 수 있습니다.

#!/bin/bash
if something ; then
    interpreter=this
    script=/some/path/to/program.real
    flags=()
else
    interpreter=that
    script=/other/path/to/program.real
    flags=(-x -y)
fi
exec "$interpreter" "${flags[@]}" "$script" "$@"

사용자의 PATHas 에 래퍼를 유지 program하고 실제 프로그램은 따로 두거나 다른 이름을 사용하십시오.

#!/bin/bash배열 때문에 해시뱅에서 사용 합니다 flags. 가변 개수의 플래그 등을 저장할 필요가 없고 그것 없이도 할 수 있는 경우 스크립트는 #!/bin/sh.

답변2

아니요, 작동하지 않습니다. 이 두 문자는 #!반드시 파일의 처음 두 문자여야 합니다(해석할 if 문의 내용을 어떻게 지정합니까?). exec()이는 실행될 파일이 스크립트(인터프리터 필요)인지 바이너리 파일(인터프리터 필요 없음)인지 결정할 때 함수 계열이 감지하는 "마법의 숫자"를 구성합니다 .

shebang 라인의 형식은 매우 엄격합니다. 인터프리터에 대한 절대 경로와 최대 하나의 인수가 필요합니다.

너 뭐야할 수 있는해야 할 일은 다음을 사용하는 것입니다 env.

#!/usr/bin/env interpreter

이제 env가는 길은대개 /usr/bin/env, 그러나 기술적으로 이는 보장되지 않습니다.

이를 통해 PATH각 시스템의 환경 변수를 조정하여 시스템을 찾을 수 있습니다 interpreter(시스템 bash또는 python갖고 있는 모든 것).perl

이 접근 방식의 단점은 인수를 인터프리터에 이식적으로 전달할 수 없다는 것입니다.

이것은 의미한다

#!/usr/bin/env awk -f

그리고

#!/usr/bin/env sed -f

일부 시스템에서는 작동하지 않을 수 있습니다.

./configure또 다른 확실한 방법은 GNU autotools(또는 일부 더 간단한 템플릿 시스템)를 사용하여 인터프리터를 찾고 스크립트가 각 시스템에 설치될 때 실행될 단계에서 파일에 대한 올바른 경로를 지정하는 것입니다 .

명시적 인터프리터를 사용하여 스크립트를 실행할 수도 있지만 이는 분명히 피하고 싶은 것입니다.

$ sed -f script.sed

답변3

다국어(두 언어 결합)로 작성할 수도 있습니다. /bin/sh 존재가 보장됩니다.

단점은 코드가 보기 흉하다는 것입니다. 단, env존재하지 않거나 /usr/bin/env 이외의 위치에 존재할 경우에는 사용할 수 있습니다. 정말 멋진 선택을 하고 싶을 때도 사용할 수 있습니다.

스크립트의 첫 번째 부분은 /bin/sh를 인터프리터로 사용하여 실행할 때 사용할 인터프리터를 결정하지만 올바른 인터프리터에 의해 실행되면 무시됩니다. 우리는 이것을 사용하여 exec쉘이 첫 번째 부분을 지나치는 것을 방지합니다.

파이썬 예:

#! /bin/sh -
''':'
# Python thinks this is a string, docstring unfortunately.
# The shell just ran the no-op : command.
find_best_python ()
{
    for candidate in pypy3 pypy python3 python; do
        if "$candidate" -c '' 2>/dev/null; then
            echo "$candidate"
            return
        fi
    done
    echo >&2 "Can't find any Python"
    false
}
interpreter="$(find_best_python)" || exit  # Replace with something fancier.
# Re-run the rest of the script with the chosen interpreter:
exec "$interpreter" "$0" "$@"
'''

print("Python code goes here")

답변4

이는 쉘 스크립트에서 인터프리터를 선택하지 않지만(각 시스템에 대한 인터프리터를 선택함) 스크립트를 실행하려는 모든 시스템에 대한 관리 액세스 권한이 있는 경우 더 쉬운 옵션입니다.

원하는 인터프리터 경로를 가리키는 기호 링크(또는 필요한 경우 하드 링크)를 만듭니다. 예를 들어, 내 시스템에서 Perl과 Python은 /usr/bin에 있습니다.

cd /bin
ln -s /usr/bin/perl perl
ln -s /usr/bin/python python

hashbang이 /bin/perl 등을 구문 분석할 수 있도록 심볼릭 링크가 생성됩니다. 또한 매개변수를 스크립트에 전달하는 기능도 유지됩니다.

관련 정보