“观察”命令的输出,直到观察到特定的字符串,然后退出


29

我正在寻找一种以编程方式监视命令输出直到观察到特定字符串然后退出的方法。这与这个问题非常相似,但我不想尾随文件,而是想“尾随”命令。

就像是:

看-n1 my_cmd | grep -m 1“字符串我正在寻找”

(但这对我不起作用。)

更新:我需要弄清楚'my_cmd'不会连续输出文本,而是需要重复调​​用直到找到字符串为止(这就是为什么我想到'watch'命令的原因)。在这方面,“ my_cmd”就像许多其他Unix命令一样,例如:ps,ls,lsof,last等。


我本以为可以tail -f像文件一样输出程序输出...我错了吗?
Joanis'1

@Joanis。您是对的,但就我而言,“ my_cmd”不会连续产生输出,必须重复调用(与大多数命令类似:ps,ls,lsof等)
gdw2 2012年

Answers:


41

使用循环:

until my_cmd | grep -m 1 "String Im Looking For"; do : ; done

代替:,您可以使用sleep 1(或0.2)简化CPU。

循环运行直到grep在命令的输出中找到字符串为止。-m 1表示“一个匹配就足够了”,即grep找到第一个匹配项后便停止搜索。

您还可以使用grep -qwhich在找到第一个匹配项后退出,但不打印匹配行。


此命令的解释将不胜感激。
Mark W

@MarkW:已更新。
choroba '16

有人提到grep -q这是另一种选择。找到字符串后,grep退出。
太阳

请注意,此命令将重复运行有问题的命令,这可能是可取的,也可能是不希望的。
艾德里安

1
@A__:这是可取的,如OP中“更新”中所述。
choroba

11
watch -e "! my_cmd | grep -m 1 \"String Im Looking For\""
  • ! 否定命令管道的退出代码
  • grep -m 1 找到字符串时退出
  • watch -e 如果发生任何错误,则返回

但这可以进行改进,以实际显示匹配的行,到目前为止已将其丢弃。


感谢您的详细说明,但它对我不起作用。我的watch命令(CentOS)没有-e标志(这应该没关系)。不过,更重要的是,当找到字符串时,监视将继续运行并且不会退出。看来,当grep -m退出时,它只会退出kills my_cmd,而不会退出watch
gdw2 2012年

不,这是重要的!,当命令的错误代码不同于0时,“-e”标志用于退出监视。由于它不存在的监视将在您的平台上继续运行。无论如何,很高兴知道,在我的Ubuntu 11.10安装上,一切都很好。有时我也对Mac OSX遇到过时的命令行工具的麻烦,到目前为止,我正在使用mac端口来获取更多最新的软件。
2012年

如果找到了模式,此操作将停止,但是直到发生这种情况,它才会显示任何输出
Mark

您可以使用tee为,但这导致一个误导换行,我不知道该怎么现在规避:watch -n1 -e "! date | tee /dev/tty | grep --color -m 1 \"17\""
数学

是的,这对我不起作用。watch找到该字符串时,它会忠实地停止观看,但是直到您按下某个键时,它才真正退出。很近。
mlissner '18年

8

对于那些具有不断向stdout写入程序的程序,您只需使用'single match'选项将其通过管道传送到grep。grep找到匹配的字符串后,它将退出,这将关闭通过管道传递给grep的进程的stdout。只要进程再次写入,此事件自然就应该导致程序正常退出。

将会发生的是,当grep退出后,该进程尝试写入已关闭的stdout时,该进程将收到SIGPIPE。这是ping的示例,否则将无限期运行:

$ ping superuser.com | grep -m 1 "icmp_seq"

此命令将与第一个成功的“ pong”匹配,然后在下次ping尝试写入stdout 时退出。


然而,

并不总是保证该进程将再次写入stdout,因此可能不会导致SIGPIPE升高(例如,在尾随日志文件时可能会发生这种情况)。在这种情况下,我设法提出的最佳解决方案是写入文件。如果您认为可以改善,请发表评论:

$ { tail -f log_file & echo $! > pid; } | { grep -m1 "find_me" && kill -9 $(cat pid) && rm pid; }

分解如下:

  1. tail -f log_file & echo $! > pid-尾部文件,将进程附加到后台,并将PID($!)保存到文件。我尝试将PID导出为变量,但是在这里和再次使用PID时似乎存在竞争条件。
  2. { ... ;}- 在一起使用这些指令,所以我们可以通过管道输出,同时保持当前上下文(保存和重新使用变量时会有所帮助,但无法得到的那部分工作)的grep
  3. | -将左侧的stdout管道到右侧的stdin
  4. grep -m1 "find_me" -查找目标字符串
  5. && kill -9 $(cat pid)- 一旦找到匹配的字符串,退出强制杀死(SIGKILL)tail进程 grep
  6. && rm pid -删除我们创建的文件

0
my_cmd | tail +1f | sed '/String Im Looking For/q'

如果tail不支持+1f语法,请尝试tail -f -n +1。(-n +1告诉它从开头开始;tail -f默认情况下从输出的最后10行开始。)


请参阅我对问题的更新。
gdw2 2012年

0

将程序调用的结果附加到文件中。然后tail -f那个文件。这样就可以了...我希望。

当您重新开始调用该程序时,您将不得不删除文件或在文件上附加一些乱码,以免再次与您要查找的内容不匹配。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.