9

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

#!/bin/bash
pipe="mypipe"
if [ ! -p $pipe ]; then
  echo 'Creating pipe'
  mkfifo $pipe
fi

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

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?

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255

2 Answers2

8

In your case, you can do simply:

tail -f $pipe | sh & 

no need for loops.

Gnudiff
  • 975
7

One way to do it:

#! /usr/bin/env bash
pipe=/path/to/pipe
[ -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
        fi
    done <"$pipe"
done

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

Satō Katsura
  • 13,368
  • 2
  • 31
  • 50