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

gdw*_*dw2 39 linux bash

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

就像是:

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

(但这对我不起作用。)

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

cho*_*oba 47

使用循环:

until my_cmd | grep -m 1 "String Im Looking For"; do : ; done
Run Code Online (Sandbox Code Playgroud)

代替:,您可以使用sleep 1(或 0.2)来减轻 CPU 负担。

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

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


mat*_*ath 13

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

但这可以改进以实际显示匹配的行,该行目前已被丢弃。


Bla*_*lia 10

对于那些拥有连续写入标准输出的程序的人,您需要做的就是使用“单一匹配”选项将其通过管道传送到 grep。一旦 grep 找到匹配的字符串,它将退出,这将关闭正在通过管道传输到 grep 的进程的标准输出。这个事件应该自然地导致程序正常退出,只要过程中再次写道

将会发生的情况是,该进程在 grep 退出后尝试写入已关闭的标准输出时将收到一个 SIGPIPE。这是一个带有 ping 的示例,否则它将无限期运行:

$ ping superuser.com | grep -m 1 "icmp_seq"
Run Code Online (Sandbox Code Playgroud)

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


然而,

并不总是保证进程会再次写入标准输出,因此可能不会引发 SIGPIPE(例如,拖尾日志文件时可能会发生这种情况)。我设法针对这种情况提出的最佳解决方案涉及写入文件;如果您认为可以改进,请发表评论:

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

打破这个:

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