Bidirectional piping, how to make two programs communicate with each other
Tags: javascript, bash, linux
Published: 2022-02-23 19:41:41

---
title: Bidirectional piping, how to make two programs communicate with each other
published: true
description: How to make two programs communicate with each other
tags: javascript,bash,linux
cover_image: https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fwinzoro.net%2Fuploads%2Fposts%2F2019-04%2F1555593968_3d-pipes-screensaver.jpg&f=1&nofb=1
---

First of all a small refresher on what piping is and how it works
when you do something like 
```bash
echo 2 | cat
```
stdout of `echo` is being piped to cat's stdin, cat writes again the result that was read from stdin to stdout and you see the result in your terminal, this is a example of unidirectional piping, bidirectional piping would be if cat could write back to echo and echo could read what was piped, basically you would have two program that can communicate with each other.

On Linux we do this creating a named pipe, which is just a special type of file using the FIFO(first in first out) method so one program can write to that file and the other can read and vice versa, the two easiest ways of creating a FIFO is using the program mkfifo, or using bash built-in function coproc, both do basically the same thing the only different is that when using coproc you end up with more elegant code depending on who you ask, let's create a simple program and implement bidirectional piping using mkfifo, which is more explicit, I'm gonna write one program in bash and the other one in javascript(node) but any language that can write to stdin, stderr and read from stdout would work(so basically all of them)
let's create three programs, prog1, prog2 and program to create the FIFO and call the other programs

**prog1.sh**
```bash
echo "bash: hello!"
read line
echo $line 1>&2
echo "bash: how are you doing?"
read line
echo $line 1>&2
```

**prog2.js**
```javascript
const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  terminal: false
});

rl.on('line', function (cmd) {
  if(cmd == 'bash: hello!') {
    console.error(cmd);
    console.log("javascript: hello!");
  }
  if(cmd == 'bash: how are you doing?') {
    console.error(cmd);
    console.log("javascript: I'm fine, thanks!");
  }
});
```
and the program to create the FIFO and call the two other programs

**start.sh**
```bash
mkfifo p1 p2 
bash ./prog1.sh > p1 < p2 &
node ./prog2.js < p1 > p2 
 
rm -rf p1 p2
```
We delete the FIFOs in the last line to avoid a warning the next time we run `bash start.sh`, the warning would just tell us that the FIFO already exist.
now we can run everything with
```bash
bash ./start.sh
``` 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kie93gqh5dqv94rbld1i.png)
 
It works!!! one program can send messages to the other program, when both programs end, start also ends, also we can only read or write to the FIFO if two program open the FIFO file, if you remove the last line of `start.sh` you can see the FIFO files that were created in the same directory.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nhk50enuvydt4tdx3f1w.png)

If you try to open the FIFO file in a text editor, your text editor will probably crash on hang indefinitely. you might think that the same thing is possible just creating regular files, but the code would be a lot more cumbersome, FIFO allows us to write pretty elegant code connecting two different programs, or two different instances of the same program, let's talk a little bit about the actual code
```bash
mkfifo p1 p2
```
This command creates two FIFO files called p1 and p2
```bash
bash ./prog1.sh > p1 < p2 &
```
here we run the first bash program and tell it to point it's `stdout` to p1 and `stdin` to p2 
```bash
node ./prog2.js < p1 > p2
```
here we run the second program and do the opposite, we tell him to read from p1 and write to p2
```bash
rm -rf p1 p2
```
This line is not required it just avoids the warning when we run `mkfifo` again the next time

Now let's have a look at the programs themselves, first the bash program
```bash
echo "bash: hello!"
read line
echo $line 1>&2
echo "bash: how are you doing?"
read line
echo $line 1>&2
```
The only think that might be confusing here if you don't know bash very well is the line
```bash
echo $line 1>&2
```
here we're redirecting from `stdout` to `stderr` if we don't do this we can't see the messages in our terminal, remember that the stdout is going to the other program and not to the terminal, if we just echoed without the redirecting the string will go to the FIFO and be read by prog2, same thing for the javascript code
```javascript
console.error(cmd);
```
we do the above so we can print to stderr, the javascript program prints the bash messages and the bash program prints the javascript messages, another difference is that the javascript program calls the same callback every time it reads something from the fifo that's why we have the if statements to identify which message was receive and reply accordingly.