#!
shebang line()을 통해 실행 파일에 여러 옵션을 전달하는 일반적인 방법이 있는지 궁금합니다 .
나는 NixOS를 사용하는데 내가 작성하는 모든 스크립트에서 shebang의 첫 번째 부분은 일반적으로 입니다 /usr/bin/env
. 문제는 뒤따르는 모든 것이 시스템에 의해 단일 파일이나 디렉터리로 해석된다는 것입니다.
bash
예를 들어, posix 모드에서 실행되는 스크립트를 작성한다고 가정해 보겠습니다 . Shebang을 작성하는 간단한 방법은 다음과 같습니다.
#!/usr/bin/env bash --posix
그러나 생성된 스크립트를 실행하려고 하면 다음 오류가 발생합니다.
/usr/bin/env: ‘bash --posix’: No such file or directory
알아요이 게시물하지만 더 일반적이고 깔끔한 솔루션이 있는지 알고 싶습니다.
편집하다: 나도 알고 있어장난스크립트, 내가 원하는 것을 달성하는 방법이 있습니다.섹션 4.3.4매뉴얼:
#!/usr/bin/env sh
exec guile -l fact -e '(@ (fac) main)' -s "$0" "$@"
!#
여기서의 비결은 두 번째 줄( but 로 시작하는 )이 code , ... 블록 내부의 주석 exec
으로 해석되므로 Guile 해석기에서 무시된다는 것입니다.sh
#!
!#
이 접근 방식을 모든 통역사에게 일반화할 수는 없나요?
두 번째 편집: 몇 가지 시도 후에 stdin
입력을 읽을 수 있는 인터프리터에 대해 다음이 작동하는 것 같습니다.
#!/usr/bin/env sh
sed '1,2d' "$0" | bash --verbose --posix /dev/stdin; exit;
sh
그러나 통역사가 작업을 완료할 때까지 프로세스가 계속되므로 이는 최적이 아닐 수 있습니다 . 어떤 피드백이나 제안이라도 대단히 감사하겠습니다.
답변1
완전히 이식 가능하지는 않지만 coreutils 8.30부터해당 문서에 따르면다음을 사용할 수 있습니다.
#!/usr/bin/env -S command arg1 arg2 ...
그래서 주어진:
$ cat test.sh
#!/usr/bin/env -S showargs here 'is another' long arg -e "this and that " too
당신은 얻을 것이다:
% ./test.sh
$0 is '/usr/local/bin/showargs'
$1 is 'here'
$2 is 'is another'
$3 is 'long'
$4 is 'arg'
$5 is '-e'
$6 is 'this and that '
$7 is 'too'
$8 is './test.sh'
궁금하다면 showargs
:
#!/usr/bin/env sh
echo "\$0 is '$0'"
i=1
for arg in "$@"; do
echo "\$$i is '$arg'"
i=$((i+1))
done
답변2
적어도 Linux를 지원해야 하는 경우에는 보편적인 솔루션이 없습니다.Linux 커널은 shebang 줄의 첫 번째 "단어" 이후의 모든 항목을 단일 인수로 처리합니다..
NixOS의 한계가 무엇인지 잘 모르겠지만 일반적으로 나는 귀하의 shebang을 다음과 같이 작성합니다.
#!/bin/bash --posix
또는 가능하다면,스크립트에서 옵션 설정:
set -o posix
또는 적절한 셸 호출을 사용하여 스크립트가 자체적으로 다시 시작되도록 할 수 있습니다.
#!/bin/sh -
if [ "$1" != "--really" ]; then exec bash --posix -- "$0" --really "$@"; fi
shift
# Processing continues
대상 언어가 처음 몇 줄(셸에서 해석됨)을 무시하도록 하는 방법을 찾는 한 이 접근 방식을 다른 언어로 일반화할 수 있습니다.
GNU coreutils
' env
버전 8.30부터 해결 방법을 사용할 수 있습니다.블랙 노드~의답변더 알아보기. (Debian 10 이상, RHEL 8 이상, Ubuntu 19.04 이상 등에서 사용할 수 있습니다.)
답변3
POSIX 표준에 대한 설명은 매우 간결합니다 #!
.
~에서exec()
시스템 인터페이스 시리즈 문서의 기본 원리 부분:
일부 역사적 구현이 쉘 스크립트를 처리하는 또 다른 방법은 파일의 처음 2바이트를 문자열로 인식
#!
하고 파일의 첫 번째 줄의 나머지 부분을 실행할 명령 해석기의 이름으로 사용하는 것이었습니다.
~에서쉘 소개 부분:
쉘은 POSIX.1-2008 시스템 인터페이스 볼륨에 정의된 파일(참고자료 참조
sh
), 옵션 또는 함수 로부터 입력을 읽습니다.-c
system()
popen()
쉘 명령 파일의 첫 번째 행이 문자로 시작하면#!
결과는 지정되지 않습니다..
이는 기본적으로 모든 구현(사용 중인 Unix)이 필요에 따라 shebang 라인 구문 분석 세부 사항을 자유롭게 수행할 수 있음을 의미합니다.
macOS(ATM을 테스트할 수 없음)와 같은 일부 Unices는 shebang 라인에서 인터프리터에 제공된 매개변수를 별도의 매개변수로 분할하는 반면, Linux 및 대부분의 다른 Unices는 인터프리터에 매개변수를 단일 옵션으로 제공합니다.
그러므로 여러 매개변수를 허용하기 위해 shebang 라인에 의존하는 것은 현명하지 않습니다.
또한보십시오Wikipedia Shebang 기사의 이식성 섹션.
모든 유틸리티나 언어에 일반화할 수 있는 간단한 솔루션은 적절한 명령줄 인수를 사용하여 실제 스크립트를 실행하는 래퍼 스크립트를 만드는 것입니다.
#!/bin/sh
exec /bin/bash --posix /some/path/realscript "$@"
개인적으로 다시 실행하려고 시도하지는 않을 것 같습니다.그 자체조금 허약한 느낌이 들기 때문이죠.
답변4
에 설명된 shebangexecve
(2)매뉴얼 페이지는 다음과 같습니다:
#! interpreter [optional-arg]
이 구문은 두 개의 공백을 허용합니다.
- 한 칸 앞에통역사경로이지만 이 공간은 선택사항입니다.
- 공백으로 구분통역사경로 및 해당 선택적 매개변수입니다.
선택적 매개변수에 대해 말할 때 복수형을 사용하지 않았으며 위의 구문 [optional-arg ...]
도 사용하지 않았습니다.최대 1개의 매개변수를 제공할 수 있습니다..
쉘 스크립트의 경우 set
스크립트 시작 부분 근처에 내장 명령을 사용할 수 있습니다. 그러면 인터프리터 매개변수를 설정할 수 있어 명령줄 매개변수를 사용하는 것과 동일한 결과를 얻을 수 있습니다.
귀하의 경우:
set -o posix
Bash 프롬프트에서 help set
사용 가능한 모든 옵션에 대한 출력을 검사합니다.