How to create a bidirectional pipe in bash?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP












2















I have a program which reads from and writes to file descriptor 3. I want to let it write to fd 3, and be able to write to the other end of the pipe interactively which the program should read over the same fd. I can create a pipe with mkfifo (mkfifo /tmp/my_pipe) and remap one end of it to fd 3 (./prog &3>/tmp/my_pipe). I keep the pipe open using cat /tmp/my_pipe. However, when the process tries to read from fd 3, it receives a SIGTTIN. Is it possible to launch the program as I intend from bash?










share|improve this question

















  • 1





    unix.stackexchange.com/questions/53641/…

    – ozzy
    Jan 8 at 22:03















2















I have a program which reads from and writes to file descriptor 3. I want to let it write to fd 3, and be able to write to the other end of the pipe interactively which the program should read over the same fd. I can create a pipe with mkfifo (mkfifo /tmp/my_pipe) and remap one end of it to fd 3 (./prog &3>/tmp/my_pipe). I keep the pipe open using cat /tmp/my_pipe. However, when the process tries to read from fd 3, it receives a SIGTTIN. Is it possible to launch the program as I intend from bash?










share|improve this question

















  • 1





    unix.stackexchange.com/questions/53641/…

    – ozzy
    Jan 8 at 22:03













2












2








2








I have a program which reads from and writes to file descriptor 3. I want to let it write to fd 3, and be able to write to the other end of the pipe interactively which the program should read over the same fd. I can create a pipe with mkfifo (mkfifo /tmp/my_pipe) and remap one end of it to fd 3 (./prog &3>/tmp/my_pipe). I keep the pipe open using cat /tmp/my_pipe. However, when the process tries to read from fd 3, it receives a SIGTTIN. Is it possible to launch the program as I intend from bash?










share|improve this question














I have a program which reads from and writes to file descriptor 3. I want to let it write to fd 3, and be able to write to the other end of the pipe interactively which the program should read over the same fd. I can create a pipe with mkfifo (mkfifo /tmp/my_pipe) and remap one end of it to fd 3 (./prog &3>/tmp/my_pipe). I keep the pipe open using cat /tmp/my_pipe. However, when the process tries to read from fd 3, it receives a SIGTTIN. Is it possible to launch the program as I intend from bash?







bash pipe mkfifo






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Jan 8 at 21:12









Holmes.SherlockHolmes.Sherlock

224110




224110







  • 1





    unix.stackexchange.com/questions/53641/…

    – ozzy
    Jan 8 at 22:03












  • 1





    unix.stackexchange.com/questions/53641/…

    – ozzy
    Jan 8 at 22:03







1




1





unix.stackexchange.com/questions/53641/…

– ozzy
Jan 8 at 22:03





unix.stackexchange.com/questions/53641/…

– ozzy
Jan 8 at 22:03










1 Answer
1






active

oldest

votes


















3














On (at least) Linux-based systems a FIFO or Named Pipe is unidirectional. In your situation you want to have a program reading and writing to the same FIFO. This gets even more tricky because you may well up with a deadlock if you exceed the pipe's internal buffer.



Two general points.



  1. You cannot usefully have two readers; if you do, you'll find that your reads will interleave nondeterministically and your data will be shared between the two readers. You will not get the same data duplicated to both readers.


  2. You can have two (or more) writers, but once again your output data will be interleaved in the order that it is received by the pipe. Unless your writers are carefully synchronised, data such as First writer and Second writer could end up being received as the garbled FirSecond wrstwrititerer.


Using the program at the bottom of this answer, consider running the following two scenarios from different terminal sessions. Then try your own variations.



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


Script for fifo.sh as follows



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


########################################################################
# Reader
#
doRead()

echo "Reading from pipe $pipe" >&2
nl <"$pipe"



########################################################################
# Writer. We pause after every line (for effect)
#
doWrite()
while IFS= read -r line; do printf "%sn" "$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 "$@"


########################################################################
#
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





share|improve this answer
























    Your Answer








    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "106"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f493331%2fhow-to-create-a-bidirectional-pipe-in-bash%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    3














    On (at least) Linux-based systems a FIFO or Named Pipe is unidirectional. In your situation you want to have a program reading and writing to the same FIFO. This gets even more tricky because you may well up with a deadlock if you exceed the pipe's internal buffer.



    Two general points.



    1. You cannot usefully have two readers; if you do, you'll find that your reads will interleave nondeterministically and your data will be shared between the two readers. You will not get the same data duplicated to both readers.


    2. You can have two (or more) writers, but once again your output data will be interleaved in the order that it is received by the pipe. Unless your writers are carefully synchronised, data such as First writer and Second writer could end up being received as the garbled FirSecond wrstwrititerer.


    Using the program at the bottom of this answer, consider running the following two scenarios from different terminal sessions. Then try your own variations.



    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


    Script for fifo.sh as follows



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


    ########################################################################
    # Reader
    #
    doRead()

    echo "Reading from pipe $pipe" >&2
    nl <"$pipe"



    ########################################################################
    # Writer. We pause after every line (for effect)
    #
    doWrite()
    while IFS= read -r line; do printf "%sn" "$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 "$@"


    ########################################################################
    #
    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





    share|improve this answer





























      3














      On (at least) Linux-based systems a FIFO or Named Pipe is unidirectional. In your situation you want to have a program reading and writing to the same FIFO. This gets even more tricky because you may well up with a deadlock if you exceed the pipe's internal buffer.



      Two general points.



      1. You cannot usefully have two readers; if you do, you'll find that your reads will interleave nondeterministically and your data will be shared between the two readers. You will not get the same data duplicated to both readers.


      2. You can have two (or more) writers, but once again your output data will be interleaved in the order that it is received by the pipe. Unless your writers are carefully synchronised, data such as First writer and Second writer could end up being received as the garbled FirSecond wrstwrititerer.


      Using the program at the bottom of this answer, consider running the following two scenarios from different terminal sessions. Then try your own variations.



      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


      Script for fifo.sh as follows



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


      ########################################################################
      # Reader
      #
      doRead()

      echo "Reading from pipe $pipe" >&2
      nl <"$pipe"



      ########################################################################
      # Writer. We pause after every line (for effect)
      #
      doWrite()
      while IFS= read -r line; do printf "%sn" "$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 "$@"


      ########################################################################
      #
      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





      share|improve this answer



























        3












        3








        3







        On (at least) Linux-based systems a FIFO or Named Pipe is unidirectional. In your situation you want to have a program reading and writing to the same FIFO. This gets even more tricky because you may well up with a deadlock if you exceed the pipe's internal buffer.



        Two general points.



        1. You cannot usefully have two readers; if you do, you'll find that your reads will interleave nondeterministically and your data will be shared between the two readers. You will not get the same data duplicated to both readers.


        2. You can have two (or more) writers, but once again your output data will be interleaved in the order that it is received by the pipe. Unless your writers are carefully synchronised, data such as First writer and Second writer could end up being received as the garbled FirSecond wrstwrititerer.


        Using the program at the bottom of this answer, consider running the following two scenarios from different terminal sessions. Then try your own variations.



        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


        Script for fifo.sh as follows



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


        ########################################################################
        # Reader
        #
        doRead()

        echo "Reading from pipe $pipe" >&2
        nl <"$pipe"



        ########################################################################
        # Writer. We pause after every line (for effect)
        #
        doWrite()
        while IFS= read -r line; do printf "%sn" "$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 "$@"


        ########################################################################
        #
        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





        share|improve this answer















        On (at least) Linux-based systems a FIFO or Named Pipe is unidirectional. In your situation you want to have a program reading and writing to the same FIFO. This gets even more tricky because you may well up with a deadlock if you exceed the pipe's internal buffer.



        Two general points.



        1. You cannot usefully have two readers; if you do, you'll find that your reads will interleave nondeterministically and your data will be shared between the two readers. You will not get the same data duplicated to both readers.


        2. You can have two (or more) writers, but once again your output data will be interleaved in the order that it is received by the pipe. Unless your writers are carefully synchronised, data such as First writer and Second writer could end up being received as the garbled FirSecond wrstwrititerer.


        Using the program at the bottom of this answer, consider running the following two scenarios from different terminal sessions. Then try your own variations.



        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


        Script for fifo.sh as follows



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


        ########################################################################
        # Reader
        #
        doRead()

        echo "Reading from pipe $pipe" >&2
        nl <"$pipe"



        ########################################################################
        # Writer. We pause after every line (for effect)
        #
        doWrite()
        while IFS= read -r line; do printf "%sn" "$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 "$@"


        ########################################################################
        #
        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






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Jan 8 at 22:15

























        answered Jan 8 at 22:02









        roaimaroaima

        43.6k554117




        43.6k554117



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Unix & Linux Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f493331%2fhow-to-create-a-bidirectional-pipe-in-bash%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown






            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            Displaying single band from multi-band raster using QGIS

            How many registers does an x86_64 CPU actually have?