소스 스크립트가 실행되지 않도록 정의하는 방법

사용자가 source실행하지 않고 쉘 스크립트를 정의하고 있습니다.

예를 들어 파일 확장자를 통해 이러한 경우를 사용자에게 암시하는 기존의 또는 지능적인 방법이 있습니까?

파일 자체에 작성할 수있는 셸 코드가 있습니까? 그러면 소스 대신 실행되는 경우 메시지를 표시하고 종료되어 사용자가이 명백한 실수를 피할 수 있도록 도와 줄 수 있습니까?



답변

bash를 실행하고 있다고 가정하면, 소스가 있지만 실행하지 않으려는 스크립트의 시작 부분에 다음 코드를 넣으십시오.

if [ "${BASH_SOURCE[0]}" -ef "$0" ]
then
    echo "Hey, you should source this script, not execute it!"
    exit 1
fi

bash 아래 ${BASH_SOURCE[0]}에는 소스가 실행 중인지 또는 실행 중인지에 관계없이 쉘이 읽고있는 현재 파일의 이름이 포함됩니다.

대조적으로, $0현재 실행중인 파일의 이름입니다.

-ef이 두 파일이 같은 파일인지 테스트합니다. 그러한 경우 사용자에게 알리고 종료합니다.

POSIX 도 -ef아닙니다 BASH_SOURCE. -efksh, yash, zsh 및 Dash가 지원 하지만 BASH_SOURCEbash가 필요합니다. 에서zsh , 그러나, ${BASH_SOURCE[0]}로 대체 될 수있다 ${(%):-%N}.


답변

실행 파일이 아닌 파일을 소스로 만들 수는 있지만 실행할 수 없으므로 첫 번째 방어선으로 실행 플래그를 설정하지 않는 것이 좋습니다.

편집 : 방금 비틀었던 트릭 : shebang을 쉘 인터프리터가 아닌 실행 파일로 /bin/false만들고 스크립트에서 오류를 반환합니다 (rc! = 0)

#!/bin/false "This script should be sourced in a shell, not executed directly"


답변

이 Stack Overflow post에 제안 된 몇 가지 방법이 있습니다.이 중 Wirawan Purwantomr.spuratic best가 제안한 함수 기반 방법을 좋아했습니다 .

Wirawan Purwanto가 제안한 가장 강력한 방법 FUNCNAME[1] 은 함수 내 에서 확인
하는 것입니다 .

function mycheck() { declare -p FUNCNAME; }
mycheck

그때:

$ bash sourcetest.sh
declare -a FUNCNAME='([0]="mycheck" [1]="main")'
$ . sourcetest.sh
declare -a FUNCNAME='([0]="mycheck" [1]="source")'

이 검사의 출력에 상당 caller값,
mainsource발신자의 상황을 구별. 를 사용
FUNCNAME[]하면 caller출력 을 캡처하고 구문 분석 할 수 있습니다 . 그래도 로컬 통화 깊이를 알고 계산해야합니다. 스크립트가 다른 함수 나 스크립트 내에서 제공되는 경우 배열 (스택)이 더 깊어집니다. ( FUNCNAME특별한 bash 배열 변수입니다. 호출 스택에 해당하는 연속 인덱스가 있어야합니다 unset.

따라서 스크립트 시작 부분에 추가 할 수 있습니다.

function check()
{
    if [[ ${FUNCNAME[-1]} != "source" ]]   # bash 4.2+, use ${FUNCNAME[@]: -1} for older
    then
        printf "Usage: source %s\n" "$0"
        exit 1
    fi
}
check


답변

스크립트를 실행하는 것이 해롭지 않고 쓸모가 없다고 가정하면 추가 할 수 있습니다

return 0 || printf 'Must be sourced, not executed\n' >&2

받는 종료 스크립트. return함수 외부에 파일이 소스되지 않으면 종료 코드가 0이 아닙니다.


답변

쉘 스크립트를 소싱 할 때 shebang 행은 무시됩니다. 잘못된 shebang을 넣으면 스크립트가 잘못 실행되었음을 사용자에게 경고 할 수 있습니다.

#!/bin/bash source-this-script
# ...

오류 메시지는 다음과 같습니다.

/bin/bash: source-this-script: No such file or directory

(임의의) 인수 이름은 이미 강력한 힌트를 제공하지만 오류 메시지는 여전히 100 % 명확하지 않습니다. 우리는 source-this-script당신의 어딘가에 있는 유틸리티 스크립트로 이것을 고칠 수 있습니다 PATH:

#!/bin/sh
echo >&2 "This script must be sourced, not executed${1:+: }${1:-!}"
exit 1

이제 오류 메시지는 다음과 같습니다.

This script must be sourced, not executed: path/to/script.sh

다른 접근법과의 비교

다른 답변과 비교할 때,이 접근 방식은 각 스크립트에 대한 최소한의 변경 만 필요합니다 (그리고 shebang 행을 사용하면 편집기에서 파일 유형 감지에 도움이되고 쉘 스크립트 언어를 지정하므로 이점도 있습니다). 단점은 다소 불명확 한 오류 메시지이거나 다른 셸 스크립트를 한 번 추가 한 것입니다.

bash path/to/script.sh그래도 @muru 덕분에 명시적인 호출을 막을 수는 없습니다 .


답변


답글 남기기