사용자가 실행해야 하는 쉘 스크립트를 정의하고 있습니다 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
. -ef
ksh, 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
그러나 올바른 통화 깊이를 얻으려면 현지 통화 깊이를 알거나 계산해야 합니다. 다른 함수나 스크립트에서 발생하는 스크립트와 같은 상황에서는 배열(스택)이 더 깊어집니다. (FUNCNAME
never 가 아닌 한 호출 스택에 해당하는 연속 인덱스를 가져야 하는 특수 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이 아닌 종료 코드를 사용하세요.