파일 설명자가 유효한지 테스트

파일 설명자가 유효한지 테스트

bash 스크립트를 열 때 3보다 크거나 같은 파일 설명자(FD)에 추가 정보를 출력하기를 원합니다. FD가 켜져 있는지 테스트하기 위해 다음 트릭을 고안했습니다.

if (printf '' 1>&3) 2>&-; then
  # File descriptor 3 is open
else
  # File descriptor 3 is not open
fi

이것은 내 요구 사항에 충분하지만 FD가 작동하는지 테스트하는 더 관용적인 방법이 있는지 궁금합니다. 나는 특히 FD 플래그 검색( 그리고 FD가 쓰기 가능한지 테스트하고 FD를 읽을 수 있는지 테스트 ) fcntl(1)을 허용하는 셸 명령에 대한 시스템 호출 매핑이 있는지 여부에 관심이 있습니다 .O_WRONLYO_RDWRO_RDONLYO_RDWR

답변1

ksh(AT&T 및 pdksh 변형) 에서는 zsh다음을 수행할 수 있습니다.

if print -nu3; then
  echo fd 3 is writeable
fi

fd에 아무 것도 쓰지 않지만 fd가 쓰기 가능한지(사용되는지 fcntl(3, F_GETFL)) 확인하고, 그렇지 않으면 오류를 보고합니다.

$ ksh -c 'print -nu3' 3< /dev/null
ksh: print: -u: 3: fd not open for writing

(으로 리디렉션할 수 있습니다 /dev/null).

bash나는 당신의 유일한 옵션은 당신의 방법처럼 fd가 성공하는지 확인하는 것이라고 생각합니다 . 그러나 이것이 fd가 쓰기 가능하다는 것을 보장하지는 않습니다(또는 그렇게 하기 위해 dup()외부 유틸리티( zsh/ ...)를 호출합니다 ).perlfcntl()

(대부분의 쉘과 마찬가지로) 대신 을 bash사용하면 추가 프로세스가 분기됩니다. 당신은 그것을 사용할 수 있습니다 :(...){...;}

if { true >&3; } 2> /dev/null

오히려 분기를 피하는 것입니다(복합 명령을 리디렉션하면 항상 하위 쉘이 생성되는 Bourne 쉘 제외). :대신 사용하지 마십시오 true.특별한내장되어 있으므로 bash가 POSIX 호환 모드에 있을 때 쉘이 종료됩니다.

그러나 다음과 같이 단축할 수 있습니다.

if { >&3; } 2> /dev/null

답변2

POSIX에서는command 애플리케이션 사용법설명은 다음과 같습니다.

때로는 특수 내장 함수의 특수 기능을 억제하면 이점이 있을 수 있습니다. 예를 들어:

command exec > unwritable-file

비대화형 스크립트를 중단시키지 않으므로 스크립트를 통해 출력 상태를 확인할 수 있습니다.

그렇기 때문에 다음과 같이 할 수 있습니다.

if    command >&3
then  echo 3 is open >&3
else  ! echo 3 is not open
fi    2<>/dev/null

또는...

{ command >&3
  printf %s\\n%.0d  string "0$(($??8:0))" >&"$(($??1:3))"
} 2<>/dev/null

누가 글을 쓸 수 있나요stdout 또는 3에 대한 ewline이 뒤따르고 \n3이 열리지 않을 때 여전히 0이 아닌 종료 상태를 전달합니다. 왜냐하면 완성된 수학이 $?궁극적으로 8진수로 변환되지 않기 때문입니다.08도착하다%소수하지만 8진수를 null로 자릅니다.00.

또는...

command exec >&3 || handle_it

하지만 을 사용하는 경우 ksh93다음과 같이 할 수 있습니다.

fds

열린 파일 설명자 목록입니다. -l그들이 어디로 가는지 보려면 추가하세요 .

답변3

열린 파일 설명자는 에서 찾을 수 있습니다 /proc/<pid>/fd. 예를 들어, 현재 셸의 열린 파일 설명자를 나열하려면 ls -l /proc/$$/fd다음 명령을 실행할 수 있습니다.

total 0
lrwx------ 1 testuser testuser 64 jun  1 09:11 0 -> /dev/pts/3
lrwx------ 1 testuser testuser 64 jun  1 09:11 1 -> /dev/pts/3
lrwx------ 1 testuser testuser 64 jun  1 09:11 2 -> /dev/pts/3
lrwx------ 1 testuser testuser 64 jun  1 09:39 255 -> /dev/pts/3

다음을 사용하여 파일을 열 때:

touch /tmp/myfile
exec 7</tmp/myfile

new 로 나열되어야 합니다 ls -l /proc/$$/fd.

lr-x------ 1 testuser testuser 64 jun  1 09:11 7 -> /tmp/myfile

이를 다시 사용하여 파일 설명자를 닫으면 exec 7>&-더 이상 나열되지 않습니다 /proc/$$/fd.

답변4

이 질문은 꽤 오래된 질문입니다. 하지만 어쨌든 내장 함수를 사용하는 것은 어떨까요?

for i in {0..5} ; do if [ -t $i ]; then echo "$i is a valid FD"; else echo "$i is INVALID FD"; fi; done

산출:

0 is a valid FD
1 is a valid FD
2 is a valid FD
3 is INVALID FD
4 is INVALID FD
5 is INVALID FD

따라서 질문에 대답하려면 다음을 권장합니다.

if [ -t 3 ]; then
  # File descriptor 3 is open
else
  # File descriptor 3 is not open
fi

관련 정보