Inter-Process Communication Between a Kotlin application and a Bash Script using Named Pipes

Jan 3, 2024

I needed a simple inter-process communication between a Kotlin application and a Bash script. After some research, I stumbled over Named Pipes. It’s a very simple concept, and exactly what I needed: On MacOS or Linux, you can use the command mkfifo to create a Named Pipe that behaves like a file. You can use one process to write into it, and another to read from it.

My simple Bash script is responsible for creating the Named Pipe, reading from it, and eventually deleting it:

#!/bin/bash
# create a named pipe
mkfifo /tmp/my-named-pipe

# read from the named pipe in a loop
while read line
do
    echo "Received: $line"

    # do something with the received line
    if [[ "$line" == "TEST" ]]; then
        # do something
    fi
done < /tmp/my-named-pipe

# clean up
rm /tmp/my-named-pipe

My Kotlin application used the Named Pipe to transfer data to the Bash script:

import java.io.File
import java.io.PrintWriter

fun main() {
    val pipe = File("/tmp/my-named-pipe")

    // ensure the named pipe exists
    if (!pipe.exists()) {
        error("Error: Named Pipe does not exist")
        return
    }

    PrintWriter(pipe).use { pipeWriter ->
        while (true) {
            pipeWriter.println("TEST") // write some data
            pipeWriter.flush()
            Thread.sleep(1000)
        }
    }
}

In this simple example, the Bash script must be started first to create the Named Pipe. Then the Kotlin Application can be started to write to it.

And that’s already it. This simple concept enables a simple and efficient inter-process communication.