skip to Main Content

Right now my setup looks like this:

command1 | buffer | command2

I want to have a 3rd command, "command3" read from the buffer as well. My attempted workaround was to start the process as a child process and simply pipe the command1 | buffer | command3. The issue with that is, not only does it lead to read errors of command1, command2 would also "steal" data from command3 or otherway around. Basicly what i want to achieve is a tee like behaviour but instead of forwarding it into a buffer and a file i want to forward it to two buffers, without command2 affecting command3 or vice versa. Kind of like this:

command1 | buffer1          | command2
              
               ---- buffer2 | command3 

It should also happen simultaneously.

How could i achieve that behaviour? Are there code or non code solutions?
Edit: I’m working with infinite streams namely audio.

2

Answers


  1. You can do something like this on bash.

    echo hello | tee >(echo command1 >&2) | echo command2

    See this answer

    Login or Signup to reply.
  2. Using tee and bash’s command substitution:

    Example commands:

    $ alias command1='perl -e'''$|=1; CORE::say for qw( a b c )'' 
    
    $ alias command2='perl -pe'''$|=1; $_ = "x $_"'' 
    
    $ alias command3='perl -pe'''$|=1; $_ = "y $_"'' 
    

    Solution:

    $ exec 3>&1   # dup2(1,3)
    
    $ command1 | tee >( command2 >&3 ) | command3
    x a
    y a
    x b
    y b
    x c
    y c
    
    $ exec 3>&-   # close(3)
    

    (Unlike the other answer posted at the same time, this one doesn’t assume STDOUT and STDERR are the same.)

    (The lines appear to be processed in lockstep by command2 and command3, which can’t be guaranteed without additional communication. To even get close, command1 needs to avoid buffering its output.)

    If you wanted a program to do this instead of using a shell, it’s simply a case of doing the following in rough details:

    1. For i in 2, 3,
      1. Create pipe pipei.
      2. Fork.
      3. If in the child,
        1. Close the write end of pipei.
        2. Tie the read end of pipei to fd 1.
        3. Execute commandi.
      4. Close the read end of pipei.
      5. Set the close-on-exec flag of the write end of pipei to true.
    2. Write to both pipes.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search