추가 파일 설명자는 언제 사용됩니까?

추가 파일 설명자는 언제 사용됩니까?

파일 설명자를 만들고 출력을 해당 파일로 리디렉션할 수 있다는 것을 알고 있습니다. 예를 들어

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

관심을 가질 수 있는 다른 예:

더 많은 예가 있습니다:

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

관련 정보