스크립트를 실행하는 인터프리터를 동적으로 선택하는 방법이 있습니까? 서로 다른 두 시스템에서 실행되는 스크립트가 있는데 사용하려는 인터프리터가 두 시스템의 서로 다른 위치에 있습니다. 결국 내가 해야 할 일은 전환할 때마다 해시뱅 라인을 변경하는 것이었습니다. 내가 하고 싶은 일은논리이것과 동일합니다(이와 같은 정확한 구성이 불가능하다는 것을 알고 있습니다):
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" "$@"
사용자의 PATH
as 에 래퍼를 유지 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 등을 구문 분석할 수 있도록 심볼릭 링크가 생성됩니다. 또한 매개변수를 스크립트에 전달하는 기능도 유지됩니다.