0

I am trying to use a named pipe to monitor the activity of a running shell script. That shell script will write to the pipe that it has "Started" processing. When it has completed processing it will write "Completed" to the pipe. A second script will perform the monitoring and will read the two messages. If the second script does not receive a "Completed" message in 5 minutes it is to send an alert.

So I found this code from the Linux Journal on using a named pipe to communicate between two processes. My immediate attempt is to get the two messages from the pipe and just display a counter as it goes through the loop, but reset back to 0 if the "Completed" message came. Adding the timing was going to be next as I wanted to make sure it was going to continuously poll the pipe for the next message. However, I am not seeing the counter increment. It appears that it waits at the read line from the pipe. Any suggestions as to what I am doing wrong?

#!/bin/bash pipe=/tmp/testpipe loopcnt=0 while true do echo "count: $loopcnt" if read line <$pipe; then if [[ "$line" == 'Started' ]]; then echo $line elif [[ "$line" == 'Completed' ]]; then echo $line loopcnt=0 fi fi ((loopcnt=loopcnt+1)) done 
2
  • unix.stackexchange.com/a/498064/108618 Commented Aug 19, 2023 at 20:28
  • @KamilMaciorowski, read -t in itself doesn't help as opening the pipe already blocks when the redirection is handled Commented Aug 19, 2023 at 22:19

1 Answer 1

2

If the write end of the pipe is not open, then opening the read end will block until a writer appears. That will happen when the shell tries to set up the redirection, before it gets to run read itself, so timeout on read with -t doesn't by itself help.

The loop should proceed if you write anything to the pipe, though, but that won't help in finding out how much time passed, let alone in detecting if too much time passes before data is read.

The easiest way to work around that is to open the pipe in read-write mode in the reader, ensuring there always is a writer.

E.g. something like this:

#!/bin/bash pipe=/tmp/testpipe if ! [[ -p "$pipe" ]]; then echo "'$pipe' isn't a pipe" exit 1 fi exec 3<> "$pipe" secs=0 timeout=5 while true; do if read -t 1 -u 3 line; then echo "read '$line'" secs=0 else echo . fi if ((++secs >= timeout)); then echo "no data within $timeout secs" break fi done echo end. 

Though note that if $pipe doesn't exist, exec 3<> "$pipe" will create it as a regular file. Even with the explicit test to see if it is a pipe, there's a possibility the pipe is removed just between the test and the open. If that happens, the reads will immediately return with a falsy status because the file contains no data.

2
  • with a few modifications for the STARTED and COMPLETED message and this is working great. Thanks. One last question in my writer I have a write to the pipe, but then processing waits in the script until the reader reads from the pipe is there a way to make processing continue without waiting for reader? Commented Aug 21, 2023 at 16:49
  • @nbmlane, there's the same thing with the writer as with the reader, opening the fifo blocks until the other end is also opened. I don't think you can use FIFOs asynchronously, so that some data would be saved inside the FIFO until a future reader comes to get it. You need to arrange for the reader to have the FIFO open the whole time. Commented Aug 21, 2023 at 18:24

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.