파일을 가져오려고 할 때 파일이 존재하지 않는다는 오류가 표시되어 무엇을 수정해야 할지 알 수 있지 않겠습니까?
예를 들어,비휘발성이것을 구성 파일/rc에 추가하는 것이 좋습니다:
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
위에서 언급했듯이 nvm.sh
존재하지 않으면 "자동 오류"가 발생합니다. 하지만 시도하면 . "$NVM_DIR/nvm.sh"
결과는 가 됩니다 FILE_PATH: No such file or directory
.
답변1
POSIX 셸에는 .
특수 내장 명령이 있어 실패하면 셸이 종료됩니다(예를 들어 일부 셸에서는 bash
POSIX 모드에서만 수행됩니다).
오류는 쉘에 따라 다릅니다. 이들 모두가 파일을 구문 분석할 때 구문 오류로 종료되는 것은 아니지만 대부분은 소스 파일을 찾거나 열 수 없을 때 종료됩니다. 소스 파일의 마지막 명령이 0이 아닌 종료 상태를 반환하는 경우( errexit
물론 해당 옵션이 켜져 있지 않은 경우) 어떤 명령도 종료된다는 사실을 알지 못합니다 .
여기서 하세요:
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
이 경우, 파일이 존재하면 소스를 가져오고 파일이 -s
존재하지 않으면(또는 여기서 비어 있으면) 파일 소스를 가져오지 않으려고 합니다.
즉, 파일이 존재하지 않는 경우 오류(POSIX 셸의 치명적인 오류)로 간주되어서는 안 되며 파일은 선택 사항으로 간주됩니다.
파일을 읽을 수 없거나 디렉터리인 경우 또는 (일부 셸에서) 파일을 구문 분석하는 동안 구문 오류가 발생하는 경우 이는 여전히 (치명적인) 오류이며 보고되어야 하는 실제 오류 조건이 됩니다.
어떤 사람들은 경쟁 조건이 있다고 주장합니다. 그런데 그게 의미하는 바는 과 사이에 파일을 삭제하면 쉘이 오류와 함께 종료된다는 것인데 [
, .
스크립트가 실행되는 동안 이 고정 경로 파일이 갑자기 사라지기 때문에 이것을 오류라고 생각하는 것이 타당하다고 생각합니다. 달리기.
반면에,
command . "$NVM_DIR/nvm.sh" 2> /dev/null
어디에서 ¹가 command
제거되었습니까?특별한명령의 속성 .
(오류 발생 시 셸을 종료하지 않음)은 아무런 영향을 미치지 않습니다.
- 오류를 숨기고
.
소스 파일에서 실행되는 명령의 오류도 숨깁니다. - 또한 잘못된 권한이 있는 파일과 같은 실제 오류 조건을 숨깁니다.
기타 일반적인 구문(예를 들어 선택적 환경 파일을 지정하는 Debian 시스템의 변환되지 않은 init 스크립트 참조)은 다음과 같습니다 grep -r /etc/default /etc/init*
.systemd
EnvironmentFile=-/etc/default/service
[ -e "$file" ] && . "$file"
파일이 존재하는지 확인하고 비어 있으면 가져오십시오. 열 수 없는 경우에도 여전히 치명적인 오류입니다(그것이 존재했거나 존재했더라도).
[ -f "$file" ]
(존재하며 다음과 같은 더 많은 변형을 볼 수 있습니다.정기적인파일),[ -r "$file" ]
(읽기 가능) 또는 이들의 조합입니다.[ ! -e "$file" ] || . "$file"
약간 더 나은 버전입니다. 파일이 존재하지 않는 것이 정상임을 더 명확하게 만드십시오. 이는 또한
$?
마지막 명령 실행의 종료 상태가 반영된다는 것을 의미합니다$file
(이전의 경우 을 얻으면 그것이 존재하지 않아서인지 명령이 실패했기 때문인지1
알 수 없습니다 ).$file
command . "$file"
파일이 존재할 것으로 예상하지만 설명할 수 없는 경우 종료하지 마십시오.
[ ! -e "$file" ] || command . "$file"
위의 조합: 파일이 존재하지 않는지는 중요하지 않습니다. POSIX 셸의 경우 파일 열기(또는 구문 분석) 실패가 보고되지만 치명적이지는 않습니다(더 적절할 수 있음
~/.profile
).
1 참고: 그러나 이는 에뮬레이션을 제외하고는 사용할 zsh
수 없습니다 command
. sh
Korn 셸에서는 source
실제로 Korn 셸의 별칭이자 command .
특별하지 않은 변형 입니다..
답변2
유지관리자의 nvm
응답:
nvm은 단순히 파일을 삭제하여 쉽게 제거할 수 있습니다. 소스 nvm의 행을 추적하는 추가 작업을 강제하는 것은 특별히 가치가 없어 보입니다.
내 설명(Stéphane의 훌륭한 설명과 Kusalananda의 의견을 결합):
더 간단하고 안전합니다.
다양한 이유로 인해 파일 누락으로 인해 시작 시 POSIX 쉘이 종료되는 것을 방지합니다. POSIX가 아닌(예: bash) 셸을 사용하는 사용자는 원하는 경우 조건을 제거할 수 있습니다.
답변3
~처럼제발린그리고스티븐 차제라스POSIX 쉘에서 존재하지 않는 파일을 얻으면 로그인이 실패한다는 것이 지적되었습니다.
그러나 파일이 존재하는지 확인하기 위해 테스트를 추가한 다음 해당 파일을 가져오려고 하면 경쟁 조건이라는 문제가 발생할 수 있습니다. 와 사이에 무언가 변경 되면 nvm.sh
방지하려는 오류가 발생할 수 있지만 이는 드문 일입니다.[ -s nvm.sh ]
. nvm.sh
일반적으로 경쟁 조건을 방지하는 방법은 원하는 작업을 시도한 다음 실패할 경우 오류를 처리하는 것입니다.
. "$NVM_DIR/nvm.sh" || echo "Sourcing $NVM_DIR/nvm.sh failed" >&2
.
위에서 언급한 것처럼 오류가 발생하면 오류 처리가 실행되기 직전에 셸이 종료되기 때문에 이는 POSIX 셸에서는 작동하지 않는 것으로 나타났습니다 .
.bash_profile
내 대답은 POSIX 쉘이 POSIX 모드에서 실행되어서는 안 되기 때문에 이 질문과 관련이 없다는 것입니다 . 따라서 어쨌든 위의 코드를 실행할 수 있습니다.
보안을 극대화하기 위해 POSIX 모드가 작동하지 않도록 하거나 다음에 설명된 기술을 사용하여 POSIX 모드가 비활성화되었는지 확인할 수 있습니다.https://unix.stackexchange.com/a/383581/3169.
Stéphane의 답변에는 모든 POSIX 쉘을 처리하는 방법에 대한 몇 가지 유용한 제안이 있습니다. 이는 nvm 작성자의 의도라고 생각하지만 여기서 묻는 질문과 약간 다르기 때문에 귀하에 따라 몇 가지 가능한 접근 방식이 있습니다. 목표.