파일 설명자를 만들고 출력을 해당 파일로 리디렉션할 수 있다는 것을 알고 있습니다. 예를 들어
exec 3<> /tmp/foo # open fd 3.
echo a >&3 # write to it
exec 3>&- # close fd 3.
하지만 파일 설명자 없이도 동일한 작업을 수행할 수 있습니다.
FILE=/tmp/foo
echo a > "$FILE"
추가 파일 설명자를 사용해야 하는 경우에 대한 좋은 예를 찾고 있습니다.
답변1
대부분의 명령에는 입력 채널(표준 입력, 파일 설명자 0)과 출력 채널(표준 출력, 파일 설명자 1)이 있거나 자체적으로 열리는 여러 파일에서 작동합니다(따라서 파일 이름을 전달합니다). (이것은 일반적으로 사용자까지 필터링하는 표준 오류(fd 2)에 추가됩니다.) 그러나 때로는 여러 소스 또는 여러 대상에서 필터 역할을 하는 하나의 명령을 사용하는 것이 편리할 때도 있습니다. 예를 들어, 다음은 파일에서 홀수 줄과 짝수 줄을 구분하는 간단한 스크립트입니다.
while IFS= read -r line; do
printf '%s\n' "$line"
if IFS= read -r line; then printf '%s\n' "$line" >&3; fi
done >odd.txt 3>even.txt
이제 홀수 라인과 짝수 라인에 서로 다른 필터를 적용하고 싶다고 가정해 보겠습니다(하지만 다시 합치지는 않습니다. 이는 다른 문제가 될 수 있으며 일반적으로 셸에서는 실행 가능하지 않습니다). 셸에서는 한 명령의 표준 출력을 다른 명령으로만 파이프할 수 있습니다. 다른 파일 설명자를 파이프하려면 먼저 fd 1로 리디렉션해야 합니다.
{ while … done | odd-filter >filtered-odd.txt; } 3>&1 | even-filter >filtered-even.txt
또 다른 간단한 사용 사례는명령의 오류 출력 필터링.
exec M>&N
스크립트의 나머지 부분에 대해 하나의 파일 설명자를 다른 파일 설명자로 리디렉션합니다(또는 다른 명령이 파일 설명자를 다시 변경할 때까지). exec M>&N
와 사이에는 기능이 일부 중복됩니다 somecommand M>&N
. 이 exec
형식은 중첩될 필요가 없기 때문에 더욱 강력합니다.
exec 8<&0 9>&1
exec >output12
command1
exec <input23
command2
exec >&9
command3
exec <&8
관심을 가질 수 있는 다른 예:
- 스크립트에서 "3>&1 1>&2 2>&3"은 무엇을 합니까?(stdout을 stderr로 바꿉니다)
- 파일 설명자 및 쉘 스크립트
- 파이프 버퍼는 얼마나 큽니까?
- Bash 스크립트는 명령이 올바르게 실행되는지 테스트합니다.
더 많은 예가 있습니다:
- 플래그가 지정된 질문
io-redirection
- 플래그가 지정된 질문
file-descriptors
- 이 사이트에서 예시를 검색하세요.내부에데이터 브라우저(Stack Exchange 데이터베이스의 공개 읽기 전용 복사본)
PS 이것은 저자가 제기한 놀라운 질문입니다.fd 3을 통한 리디렉션을 사용하는 사이트에서 가장 많이 찬성된 게시물!
답변2
다음은 bash 스크립트 채팅 컨트롤로 추가 FD를 사용하는 예입니다.
#!/bin/bash
log() {
echo $* >&3
}
info() {
echo $* >&4
}
err() {
echo $* >&2
}
debug() {
echo $* >&5
}
VERBOSE=1
while [[ $# -gt 0 ]]; do
ARG=$1
shift
case $ARG in
"-vv")
VERBOSE=3
;;
"-v")
VERBOSE=2
;;
"-q")
VERBOSE=0
;;
# More flags
*)
echo -n
# Linear args
;;
esac
done
for i in 1 2 3; do
fd=$(expr 2 + $i)
if [[ $VERBOSE -ge $i ]]; then
eval "exec $fd>&1"
else
eval "exec $fd> /dev/null"
fi
done
err "This will _always_ show up."
log "This is normally displayed, but can be prevented with -q"
info "This will only show up if -v is passed"
debug "This will show up for -vv"
답변3
명명된 파이프(fifo)의 컨텍스트에서 비차단 파이프 동작은 추가 파일 설명자를 사용하여 달성됩니다.
(
rm -f fifo
mkfifo fifo
exec 3<fifo # open fifo for reading
trap "exit" 1 2 3 15
exec cat fifo | nl
) &
bpid=$!
(
exec 3>fifo # open fifo for writing
trap "exit" 1 2 3 15
while true;
do
echo "blah" > fifo
done
)
#kill -TERM $bpid
답변4
이는 추가 파일 설명자를 사용하는 것이 적절해 보이는 또 다른 경우(Bash)입니다.
env -i bash --norc # clean up environment
set +o history
read -s -p "Enter your password: " passwd
exec 3<<<"$passwd"
mycommand <&3 # cat /dev/stdin in mycommand