开发者

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

开发者 https://www.devze.com 2023-03-31 08:39 出处:网络
I\'m trying to write a ba开发者_如何学编程sh 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

I'm trying to write a ba开发者_如何学编程sh 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?


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.


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


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.


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.


Sorry for the late response but a simpler way would to use wait. wait is a BASH built-in command which waits for a process to finish

Following is the excerpt from the MAN page.

  wait [n ...]
        Wait  for each specified process and return its termination sta-
        tus.  Each n may be a process ID or a job  specification;  if  a
        job  spec  is  given,  all  processes in that job's pipeline are
        waited for.  If n is not given, all currently active child  pro-
        cesses  are  waited  for,  and  the return status is zero.  If n
        specifies a non-existent process or job, the  return  status  is
        127.   Otherwise,  the  return  status is the exit status of the
        last process or job waited for.

For further reference on usage: Refer to wiki page

0

精彩评论

暂无评论...
验证码 换一张
取 消