stderr 및 stdout을 파일로 리디렉션하면 오류가 발생합니까?

stderr 및 stdout을 파일로 리디렉션하면 오류가 발생합니까?

filename파일( ...)을 매개변수로 사용하고 stdout 및 stderr을 이라는 파일로 리디렉션하는 스크립트를 작성 중입니다 filename.output. 파일에는 한 번만 bash하려는 명령이 포함되어 있습니다(파일의 명령을 여러 번 실행해서는 안 되는 경우, 즉 mkdir또는 rmdir). 매개변수를 반복할 때 이 명령이 작동하는 것으로 나타났습니다.

bash $a &> "$(basename $a).output"

.output그러나 어떤 이유로든 생성에 실패할 경우를 대비해 이 명령의 오류 상태를 사용하고 싶습니다 .

if ! bash $a &> "$(basename $a).output"
    then
        echo >&2 "failed to create $(basename $a).output"
fi

이렇게 하면 내 if 문은 항상 true로 평가됩니다.제 생각에는stdout 또는 stderr이 실패하려면 리디렉션이 필요하지만 둘 다 필요하지 않기 때문입니다. 내가 테스트하고 있는 명령은 stderr과 stdout을 모두 생성하는 경우가 거의 없습니다. 즉, 이와 같은 명령은 datestdout을 생성하지만 stderr은 생성하지 않으므로 stderr을 리디렉션할 수 없기 때문에 0이 아닌 반환 값이 생성됩니다.

코드가 올바르게 작동하지 않는 이유에 대한 내 분석이 정확합니까? 그렇다면 stdout 리다이렉션과 stderr 리다이렉션의 실패를 별도로 확인하여 .output언제 생성되지 않았는지 정확히 알 수 있는 방법이 있나요?

편집하다:오류를 생성한 명령이 포함된 파일이 있을 bash "$a"때마다 전체 if 문이 true로 평가되었기 때문에 실제로 문제가 구성 요소에 있다는 것을 알았습니다 . $a이제 내 질문은 stdout 및 stderr를 리디렉션하면 내가 알아야 할 오류가 발생하는 상황이 있습니까?입니다.

답변1

당신이 그렇게한다면

if ! bash $a &> "$(basename $a).output"; then

리디렉션에서 오류가 발생하거나 스크립트가 실행되지만 0이 아닌 종료 상태를 반환하는 경우 if 문의 기본 분기가 실행됩니다. 이 &> file연산자는 stdout 및 stderr과 동일 > file 2>&1하지만 관련된 파일이 하나뿐이므로 한 리디렉션은 성공하고 다른 리디렉션은 실패하게 만드는 방법을 찾는 것이 어려울 것입니다. 권한 문제, 존재하지 않는 경로, 디스크 가득 참 등 파일 생성에 대한 다양한 이유로 인해 리디렉션이 실패할 수 있습니다.

테스트 스크립트를 작성해 보겠습니다. 이것은 단지 무언가를 인쇄할 뿐이며, 인수를 제공하면 오류와 함께 종료됩니다.

$ cat test.sh
#!/bin/bash
echo test script
if [ "$#" != 0 ]; then
    echo exiting with error
    exit 1
fi
$ chmod +x test.sh

여기서는 리디렉션이 실패합니다( ./non-existing-dir/실제로 존재하지 않기 때문에).

$ if ! ./test.sh > ./non-existing-dir/test.output; then 
    echo "it failed (for some reason)"; fi
bash: ./non-existing-dir/test.output: No such file or directory
it failed (for some reason)

여기서는 리디렉션이 성공하고 출력이 파일로 수집되지만 스크립트 자체는 실패 상태를 반환합니다.

$ rm -f test.output
$ if ! ./test.sh 1 > ./test.output; then
    echo "it failed (for some reason)"; fi
it failed (for some reason)

$ cat test.output 
test script
exiting with error

리디렉션 시 오류를 놓칠 수 없습니다. 오류로 인해 명령이 0이 아닌 상태로 종료됩니다. 그러나 정확한 값은 정의되지 않고 셸에 따라 다르므로 이를 사용하여 리디렉션 실패와 스크립트 자체의 실패를 구별할 수 없습니다. POSIX 쉘 명령 언어 정의는 2.8.2 명령의 종료 상태로 표현됩니다.

단어 확장 또는 리디렉션 중에 명령이 실패하는 경우 종료 상태는 1에서 125(포함) 사이여야 합니다.

Bash 매뉴얼에는 비슷한 내용이 나와 있습니다.3.7.1 간단한 명령 확장.


이제 리디렉션 오류를 구체적으로 확인하려면 다음을 수행하세요.할 수 있는이렇게 하려면 프로그램을 실행하기 전에 별도로 리디렉션을 켜면 됩니다. 예를 들어, 다음과 같은 스크립트를 사용하여 프로그램을 실행할 수 있습니다.

$ cat redir.sh 
#!/bin/sh

outfile="${1?please define output file}"
cmd="${2?please define command to run}"
shift 2

if ! exec 9> "$outfile"; then
    echo "error: cannot create redirection to '$outfile'"
    exit 1
fi

if ! "$cmd" "$@" >&9 2>&9; then
    echo "error: script '$cmd' failed"
    exit 1
fi
exec 9>&-         # close the output fd

이제 실패한 리디렉션이 다음과 같이 감지됩니다.

$ bash redir.sh ./non-existing-dir/test.output ./test.sh
redir.sh: line 8: ./non-existing-dir/test.output: No such file or directory
error: cannot create redirection to './non-existing-dir/test.output'

스크립트도 실패합니다.

$ bash redir.sh ./test.output ./test.sh 1
error: script './test.sh' failed

관련 정보