Brad
Brad

Reputation: 6105

How can I wait for certain output from a process then continue in Bash?

I'm trying to write a bash script to do some stuff, start a process, wait for that process to say it's ready, and then do more stuff while that process continues to run. The issue I'm running into is finding a way to wait for that process to be ready before continuing, and allowing it to continue to run.

In my specific case I'm trying to setup a PPP connection. I need to wait until it has connected before I run the next command. I would also like to stop the script if PPP fails to connect. pppd prints to stdout.

In psuedo code what I want to do is:

[some stuff]
echo START

[set up the ppp connection]
pppd <options> /dev/ttyUSB0
while 1
  if output of pppd contains "Script /etc/ppp/ipv6-up finished (pid ####), status = 0x0"
    break
  if output of pppd contains "Sending requests timed out"
    exit 1

[more stuff, and pppd continues to run]
echo CONTINUING

Any ideas on how to do this?

Upvotes: 52

Views: 44385

Answers (4)

Ivin
Ivin

Reputation: 1101

I had to do something similar waiting for a line in /var/log/syslog to appear. This is what worked for me:

FILE_TO_WATCH=/var/log/syslog
SEARCH_PATTERN='file system mounted'

tail -f -n0 ${FILE_TO_WATCH} | grep -qe ${SEARCH_PATTERN}

if [ $? == 1 ]; then
    echo "Search terminated without finding the pattern"
fi

It pipes all new lines appended to the watched file to grep and instructs grep to exit quietly as soon as the pattern is discovered. The following if statement detects if the 'wait' terminated without finding the pattern.

Upvotes: 34

dimba
dimba

Reputation: 27571

If you go with expect, as @sblom advised, please check autoexpect.

You run what you need via autoexpect command and it will create expect script. Check man page for examples.

Upvotes: 0

Brad
Brad

Reputation: 6105

The quickest solution I came up with was to run pppd with nohup in the background and check the nobup.out file for stdout. It ended up something like this:

sudo nohup pppd [options] 2> /dev/null &
#  check to see if it started correctly
PPP_RESULT="unknown"
while true; do
  if [[ $PPP_RESULT != "unknown" ]]; then
    break
  fi
  sleep 1
  # read in the file containing the std out of the pppd command
  #  and look for the lines that tell us what happened
  while read line; do
    if [[ $line == Script\ /etc/ppp/ipv6-up\ finished* ]]; then
      echo "pppd has been successfully started"
      PPP_RESULT="success"
      break
    elif [[ $line == LCP:\ timeout\ sending\ Config-Requests ]]; then
      echo "pppd was unable to connect"
      PPP_RESULT="failed"
      break
    elif [[ $line == *is\ locked\ by\ pid* ]]; then
      echo "pppd is already running and has locked the serial port."
      PPP_RESULT="running"
      break;
    fi
  done < <( sudo cat ./nohup.out )
done

Upvotes: 6

sblom
sblom

Reputation: 27343

There's a tool called "Expect" that does almost exactly what you want. More info: http://en.wikipedia.org/wiki/Expect

You might also take a look at the man pages for "chat", which is a pppd feature that does some of the stuff that expect can do.

Upvotes: 4

Related Questions