【问题标题】:How can I wait for certain output from a process then continue in Bash?如何等待某个进程的某些输出然后在 Bash 中继续?
【发布时间】:2011-11-04 01:56:36
【问题描述】:

我正在尝试编写一个 bash 脚本来做一些事情,启动一个进程,等待该进程说它准备好了,然后在该进程继续运行的同时做更多的事情。我遇到的问题是找到一种方法来等待该进程准备好再继续,并允许它继续运行。

在我的具体情况下,我正在尝试建立一个 PPP 连接。在运行下一个命令之前,我需要等到它已连接。如果 PPP 连接失败,我也想停止脚本。 pppd 打印到标准输出。

在伪代码中我想做的是:

[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

关于如何做到这一点的任何想法?

【问题讨论】:

  • per pppd man page 'Diagnostics 使用工具 LOG_DAEMON 将消息发送到 syslog 守护程序。 ...有关 syslog 守护进程将在何处写入消息的详细信息,请参阅 syslog(8) 文档。在大多数系统上,syslog 守护程序使用 /etc/syslog.conf 文件来指定 syslog 消息的目的地。您可能需要编辑该文件以适应。 .... 您是否看到系统日志中出现了什么样的消息?您应该能够让您的 while 循环扫描文件,寻找最新的消息。祝你好运。

标签: bash


【解决方案1】:

有一个名为“Expect”的工具几乎可以完全满足您的需求。更多信息:http://en.wikipedia.org/wiki/Expect

您还可以查看“聊天”的手册页,这是一个 pppd 功能,可以完成一些预期可以做的事情。

【讨论】:

  • expect 工作正常,但我如何让expect 退出和生成的进程(pppd)在后台继续?
【解决方案2】:

如果您按照@sblom 的建议选择expect,请查看autoexpect

您通过autoexpect 命令运行您需要的内容,它将创建expect 脚本。 查看man page 获取示例。

【讨论】:

    【解决方案3】:

    我想出的最快解决方案是在后台使用 nohup 运行 pppd 并检查 nobup.out 文件中的标准输出。结果是这样的:

    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
    

    【讨论】:

      【解决方案4】:

      我不得不做类似的事情来等待 /var/log/syslog 中的一行出现。这对我有用:

      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
      

      它将所有附加到监视文件的新行通过管道传输到 grep 并指示 grep 在发现模式后立即退出。下面的 if 语句检测“等待”是否在没有找到模式的情况下终止。

      【讨论】:

      • 在 linux 上,像这样在 'tail' 命令前面加上前缀应该可以在 10 秒后终止:timeout --signal=SIGINT 10 tail ...。在 Mac 上,您必须先使用 MacPorts 或类似工具安装它。
      • 在 Ubuntu 上不起作用,首先你必须通过 -n1 从尾部获取任何输出,然后 grep 在匹配时实际上不会退出,因为管道仍然打开我猜.此外,您可能需要尾部参数 --pid,而不是超时。
      【解决方案5】:

      很抱歉回复晚了,但更简单的方法是使用等待。 wait 是 BASH 内置命令,它等待进程完成

      以下是 MAN 页面的摘录。

        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.
      

      更多用法参考: Refer to wiki page

      【讨论】:

      • 这个答案并没有解决关于这段话的 OPs 问题:“我遇到的问题是找到一种方法来等待该过程准备好在继续之前,并允许它继续运行。”
      猜你喜欢
      • 2012-03-10
      • 2016-08-09
      • 1970-01-01
      • 1970-01-01
      • 2019-08-04
      • 2015-08-19
      • 2020-03-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多