오류에도 불구하고 대시 쉘 스크립트를 계속 실행하는 방법은 무엇입니까?

오류에도 불구하고 대시 쉘 스크립트를 계속 실행하는 방법은 무엇입니까?

파일 끝까지 실행되도록 설계된 대시 쉘 스크립트가 있습니다.

#!/usr/bin/dash
# File b_shell
. a_nonexistent_file
echo "I want to print this line despite any previous error."

그러나 존재하지 않는 파일을 가져오는 데 실패하면 실행이 중지됩니다.

$ ./b_shell
./b_shell: 3: .: a_nonexistent_file: not found

인터넷에서 쉽게 찾을 수 있는 set -e및 등의 후보 솔루션을 시도했지만 소용이 없었습니다.|| true

추가 정보:

  1. Bash, tcsh 등과 같은 다른 쉘을 사용할 수 없습니다. 제발 나를 바꾸게 만들지 마세요.
  2. 아래와 같이 스크립트를 중지하지 않는 다른 "찾을 수 없음" 오류를 발견했습니다.
#!/usr/bin/dash
# File b_shell_ok
a_nonexistent_command
ls a_nonexistent_file
echo "This line is printed despite any previous error."
$ ./b_shell_ok
./b_shell_ok: 3: a_nonexistent_command: not found
ls: cannot access 'a_nonexistent_file': No such file or directory
This line is printed despite any previous error.

답변1

.특별한 내장 함수이기 때문입니다 . 이는 POSIX 요구 사항입니다. 대부분의 다른 POSIX 셸도 이 작업을 수행하지만 해당 posix/sh/ksh 모드에 있을 때만(호출될 때 포함 bash) .zshsh

특수 내장 함수의 특수성을 제거하는 POSIX 방법은 해당 함수에 접두사를 붙이는 것입니다 command.

$ dash -c 'command . /x; echo here'
dash: 1: .: cannot open /x: No such file
here

exit이는 소스 파일이 호출되거나 내용을 해석하는 동안 치명적인 오류가 발생하는 경우 쉘이 종료되는 것을 방지하지 않습니다. 대시(예를 들어 반대)의 경우 bash -o posix소스 파일에 내장된 특수 함수가 실패해도 셸이 종료되지는 않지만 command.

이 옵션도 활성화된 경우 errexit소스 파일을 열 수 없으면 쉘은 계속 종료되지만 이번에는 command0이 아닌 종료 상태를 반환합니다.

$ dash -o errexit -c 'command . /x; echo "$? here"'
dash: 1: .: cannot open /x: No such file

해결책은 오류를 처리하는 것입니다.

$ dash -o errexit -c 'command . /x || echo "that is fine"; echo "$? here"'
dash: 1: .: cannot open /x: No such file
that is fine
0 here

또는:

$ dash -o errexit -c 'command . /x && : non-fatal; echo "$? here"'
dash: 1: .: cannot open /x: No such file
2 here

(또는 command .// 문의 조건부 부분을 호출하세요).ifwhileuntil

이 경우 ( 예와 달리 dash적어도 현재 버전 ) 소스 파일의 코드 평가 효과가 취소되지는 않습니다.bash -o posixerrexit

$ dash -ec 'command . ./file || echo fine; echo here'
before
$ bash -o posix -ec 'command . ./file || echo fine; echo x'
before
after
x

errexit가장 간단한 스크립트를 제외하고는 여러 가지 이유 중 하나로 피하는 것이 가장 좋습니다.

zsh는 commandPOSIX보다 앞서며 의미가 다릅니다. command .sh 에뮬레이션/POSIX 모드가 아닌 경우에는 사용할 수 없습니다.

이 오류를 방지하려면 stderr을 삭제하는 동안 일부 fd에서 파일을 열고 사전에 TOCTOU 경주와 함께 제공되는 검사를 수행하는 대신 해당 파일을 가져올 수 있습니다 /dev/fd/n.

$ dash -c '{ command . /dev/fd/3; } 4>&2 2> /dev/null 3< file 2>&4 4>&-; echo here'
here

리디렉션이 실패하면 리디렉션된 명령(여기서는명령 그룹)이 실행되지 않으므로 쉘은 특수 내장 기능을 실행하려고 시도하지 않으므로 쉘 종료로 인한 부작용을 피할 수 있습니다. OS가 Linux 또는 Cygwin이고 열기가 a와 같지 않은 command경우 접두사를 추가하고 파일이 fd 3에서 열린 이후 파일 권한이 변경된 경우 여전히 실패할 수 있습니다./dev/fd/xdup(x)

답변2

그것은POSIX 요구 사항이러한 실패는 쉘을 중단해야 합니다:

읽을 수 있는 파일이 없으면 비대화형 쉘이 종료됩니다.

따라서 유일한 옵션은 파일이 존재하고 필요할 때 읽을 수 있는지 확인하여 명령을 보호하는 것입니다.

[ -f file ] && [ -r file ] && . ./file

if파일이 존재하지 않는 경우 오류 또는 경고 메시지를 인쇄하기 위해 이를 전체 명령문으로 확장할 수도 있습니다.

관련 정보