가져오지만 실행하지 않는 쉘 스크립트를 정의하는 방법

가져오지만 실행하지 않는 쉘 스크립트를 정의하는 방법

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

파일 확장자를 통해 사용자에게 이러한 상황을 경고하는 전통적이거나 현명한 방법이 있습니까?

파일을 가져오는 대신 실행하면 메시지를 에코하고 종료하여 사용자가 이 명백한 오류를 피할 수 있도록 파일 자체에 작성할 수 있는 셸 코드가 있습니까?

답변1

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 BASH_SOURCE가 필요합니다. 존재하다zsh그러나 ${BASH_SOURCE[0]}로 대체할 수 있습니다 ${(%):-%N}.

답변2

실행 불가능한 파일을 얻을 수는 있지만 실행할 수는 없으므로 첫 번째 방어선으로 실행 가능 플래그를 설정하지 않는 것이 좋은 팁이 될 것입니다...

편집: 방금 우연히 발견한 트릭: 쉘 인터프리터가 아닌 실행 파일을 shebang으로 만들면 /bin/false스크립트에서 오류(rc!=0)가 반환됩니다.

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

답변3

여러 가지 방법이 제안되어 있습니다.이 스택 오버플로 게시물, 그중에서 나는 기능 기반 제안을 좋아합니다.위라반 푸완토그리고스프라틱 씨최고:

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이는 출력 값을 확인 main하고 source호출자의 컨텍스트를 구별하는 것과 같습니다 . 를 사용하면 출력을 캡처하고 구문 분석하는 시간이 FUNCNAME[]절약됩니다 . caller그러나 올바른 통화 깊이를 얻으려면 현지 통화 깊이를 알거나 계산해야 합니다. 다른 함수나 스크립트에서 발생하는 스크립트와 같은 상황에서는 배열(스택)이 더 깊어집니다. ( FUNCNAMEnever 가 아닌 한 호출 스택에 해당하는 연속 인덱스를 가져야 하는 특수 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

답변4

스크립트 실행이 해롭기보다는 쓸모없다고 가정하면 다음을 추가할 수 있습니다.

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

도착하다스크립팅됨. return파일을 가져오는 중이 아닌 이상 함수 외부에 0이 아닌 종료 코드를 사용하세요.

관련 정보