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_WRONLY
O_RDWR
O_RDONLY
O_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
/ ...)를 호출합니다 ).perl
fcntl()
(대부분의 쉘과 마찬가지로) 대신 을 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이 뒤따르고 \n
3이 열리지 않을 때 여전히 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