Bash에서 양방향 파이프를 만드는 방법은 무엇입니까?

Bash에서 양방향 파이프를 만드는 방법은 무엇입니까?

파일 설명자를 읽고 쓰는 프로그램이 있습니다 3. 나는 그것이 fd에 쓰고 3파이프의 다른 쪽 끝에 대화식으로 쓸 수 있기를 원하며 프로그램은 동일한 fd를 읽어야 합니다. mkfifo()를 사용하여 파이프를 만들고 mkfifo /tmp/my_pipe파이프의 한쪽 끝을 fd 3( ./prog &3>/tmp/my_pipe) 에 다시 매핑 할 수 있습니다 . 나는 Keep Pipe Open 을 사용합니다 cat /tmp/my_pipe. 그런데 프로세스가 fd 를 읽으려고 3하면 SIGTTIN.

답변1

(적어도) Linux 기반 시스템에서는 FIFO 또는 명명된 파이프가 단방향입니다. 귀하의 경우 동일한 FIFO를 읽고 쓰는 프로그램을 원합니다. 파이프의 내부 버퍼를 초과하면 교착 상태에 빠질 수 있으므로 이는 더욱 까다로워집니다.

두 가지 일반적인 사항.

  1. 두 명의 리더를 가질 수 없습니다. 그렇게 하면 읽기가 비결정적으로 인터리브되고 데이터가 두 리더 간에 공유됩니다. 동일한 데이터를 두 판독기에 복사하지 않습니다.

  2. 두 개 이상의 작성기를 가질 수 있지만 출력 데이터는 파이프에서 수신한 순서대로 다시 인터리브됩니다. 작성자가 주의 깊게 동기화하지 않으면 First writer및 와 같은 데이터가 Second writer횡설수설로 간주될 수 있습니다 FirSecond wrstwrititerer.

이 답변의 맨 아래에 있는 프로그램을 사용하여 서로 다른 터미널 세션에서 다음 두 가지 시나리오를 실행하는 것을 고려해 보십시오. 그런 다음 자신만의 변형을 시도해 보세요.

First terminal                Second terminal               Third terminal
--------------------          --------------------          --------------------
./fifo.sh read                ./fifo.sh read                ./fifo.sh write /etc/hosts

First terminal                Second terminal               Third terminal
--------------------          --------------------          --------------------
./fifo.sh write /etc/passwd   ps -ef | ./fifo.sh write      ./fifo.sh read

First terminal                Second terminal               Third terminal
--------------------          --------------------          --------------------
./fifo.sh both /etc/passwd

스크립트 fifo.sh는 다음과 같습니다

#!/bin/bash
#
pipe=/tmp/mypipe


########################################################################
# Reader
#
doRead()
{
    echo "Reading from pipe $pipe" >&2
    nl <"$pipe"
}


########################################################################
# Writer. We pause after every line (for effect)
#
doWrite()
{
    [[ $# -eq 0 ]] && set -- -
    echo "Writing to pipe $pipe" >&2
    cat "$@" | while IFS= read -r line; do printf "%s\n" "$line"; sleep 1; done >>"$pipe"
}


########################################################################
# Reader-Writer. We pause after every line (for effect)
#
doBoth()
{
    [[ $# -eq 0 ]] && set -- -
    echo "Reading and writing to pipe $pipe" >&2
    exec 3<>"$pipe"
    nl <&3 & readPID=$!
    cat "$@" | while IFS= read -r line; do printf "%s\n" "$line"; sleep 1; done >&3
    kill $readPID 2>/dev/null
}


########################################################################
#
action="$1"
shift

if [[ ! -p "$pipe" ]]
then
    echo "Creating pipe $pipe" >&2
    mkfifo "$pipe"
fi


case "$action" in
    read*)      doRead "$@" ;;
    write*)     doWrite "$@" ;;
    both)       doBoth "$@" ;;
esac

관련 정보