I need to write a bash program that runs commands echoed to a named pipe it reads, but I cannot get it work only when a command is sent. It keeps repeating the last command until a new one is written.

That is:

  1. Execute ./read_pipe.sh
  2. It waits until a command is echoed to pipe and reads it.
  3. It executes the command once. <- What doesn't work. It keeps executing it forever.
  4. Repeat from step 2.

My read_pipe.sh

if [ ! -p $pipe ]; then
  echo 'Creating pipe'
  mkfifo $pipe

while true
  if read line <$pipe; then
    COMMAND=$(cat $pipe)
    echo "Running $COMMAND ..."
    # sh -c $COMMAND

If I cat "echo 'Hello World'" > mypipe the output is this forever:

Running "echo 'Hello World'" ...
Running "echo 'Hello World'" ...
Running "echo 'Hello World'" ...
Running "echo 'Hello World'" ...

How can I run the command once and wait for another echoed command?


One way to do it:

#! /usr/bin/env bash
[ -p "$pipe" ] || mkfifo -m 0600 "$pipe" || exit 1
while :; do
    while read -r cmd; do
        if [ "$cmd" ]; then
            printf 'Running %s ...\n' "$cmd"
            # sh -c "$cmd" sh
    done <"$pipe"

It's probably a really bad idea to uncomment the sh line though.

| improve this answer | |
  • I tried your solution, but It doesn't work properly. It executes the command once, but then your program exits. The intended way is keep executing the script, and when a new command is echoed to pipe, execute it. – Pedro Adame Vergara Jun 6 '17 at 8:05
  • Ok, I added a loop around it. – Satō Katsura Jun 6 '17 at 8:10
  • That's exactly what I've done. It executes the command sent to pipe forever until a new one is sent. I want it to be executed only once, and then wait for another command. – Pedro Adame Vergara Jun 6 '17 at 8:11
  • 1
    This is not what I'm seeing here. shrug – Satō Katsura Jun 6 '17 at 8:29
  • 1
    Sorry @SatoKatsura I've just found the solution: rm -f pipe && mkfifo pipe. Now it works correctly. For some reason it was a simple text file. -.-' – Pedro Adame Vergara Jun 6 '17 at 8:58

In your case, you can do simply:

tail -f $pipe | sh & 

no need for loops.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.