我正在寻找一种方法来以编程方式观察命令的输出,直到观察到特定的字符串然后退出。这与这问题,但我不想拖尾文件,而是想“拖尾”命令。
就像是:
watch -n1 my_cmd | grep -m 1 "String Im Looking For"
(但这对我不起作用。)
更新:我需要澄清的是,它不会my_cmd
连续输出文本,而是需要反复调用,直到找到字符串(这就是我想到该watch
命令的原因)。在这方面,它与许多其他 Unix 命令类似,my_cmd
例如:ps
、、、、等。ls
lsof
last
答案1
使用循环:
until my_cmd | grep -m 1 "String Im Looking For"; do : ; done
:
您可以使用(或 0.2)来代替,sleep 1
以减轻 CPU 负担。
循环运行,直到 grep 在命令的输出中找到该字符串。-m 1
表示“一次匹配就足够了”,即 grep 在找到第一个匹配后停止搜索。
您还可以使用grep -q
它在找到第一个匹配项后退出,但不打印匹配的行。
答案2
watch -e "! my_cmd | grep -m 1 \"String Im Looking For\""
!
否定命令管道的退出代码grep -m 1
找到字符串后退出watch -e
如果发生任何错误则返回
但这可以得到改进,以实际显示迄今为止被丢弃的匹配行。
答案3
对于那些拥有不断向 stdout 写入的程序的人来说,您需要做的就是使用“单一匹配”选项将其通过管道传输到 grep。一旦 grep 找到匹配的字符串,它就会退出,从而关闭通过管道传输到 grep 的进程上的 stdout。此事件应该自然导致程序正常退出只要进程再次写入。
实际情况是,在 grep 退出后,当进程尝试写入已关闭的标准输出时,它将收到 SIGPIPE。下面是 ping 的示例,否则它将无限期运行:
$ ping superuser.com | grep -m 1 "icmp_seq"
此命令将匹配第一个成功的“pong”,然后在下次ping
尝试写入标准输出时退出。
然而,
进程不一定能再次写入 stdout,因此可能不会引发 SIGPIPE(例如,在跟踪日志文件时可能会发生这种情况)。针对这种情况,我设法想出的最佳解决方案是写入文件;如果您认为可以改进,请发表评论:
$ { tail -f log_file & echo $! > pid; } | { grep -m1 "find_me" && kill -9 $(cat pid) && rm pid; }
具体来说:
tail -f log_file & echo $! > pid
- 跟踪文件,将进程附加到后台,并将 PID ($!
) 保存到文件中。我尝试将 PID 导出到变量,但似乎此处与再次使用 PID 之间存在竞争条件。{ ... ;}
-团体这些命令组合在一起,这样我们就可以在保持当前上下文的同时将输出传送到 grep (有助于保存和重用变量,但无法使该部分正常工作)|
- 将左侧的标准输出通过管道传输到右侧的标准输入grep -m1 "find_me"
- 找到目标字符串&& kill -9 $(cat pid)
- 强制终止(SIGKILL)该tail
进程后grep
一旦找到匹配的字符串就退出&& rm pid
- 删除我们创建的文件
答案4
my_cmd | tail +1f | sed '/String Im Looking For/q'
如果tail
不支持该+1f
语法,请尝试tail -f -n +1
。 (-n +1
告诉它从头开始;tail -f
默认情况下从最后 10 行输出开始。)