Linux:阻塞,直到一个文件中匹配的string(“tail + grep with blocking”)

在bash / GNU工具中是否存在一些单行的方法,直到在文件中匹配一个string? 理想情况下,超时。 我想避免多线循环。

更新:似乎我应该强调,我希望过程结束时,string匹配。

Solutions Collecting From Web of "Linux:阻塞,直到一个文件中匹配的string(“tail + grep with blocking”)"

感谢两个答案,但重要的是,过程阻塞,直到找到,然后结束。 我找到了这个:

grep -q 'PATTERN' <(tail -f file.log) 

-q没有多少便携性,但是我只会使用红帽企业Linux,所以没关系。 和超时:

 timeout 180 grep -q 'PATTERN' <(tail -f file.log) 

我使用sed而不是grep来创建变体,打印所有解析的行。

 sed '/PATTERN/q' <(tail -n 0 -f file.log) 

该脚本在https://gist.github.com/2377029

 tail -f file | grep word | head -n1 

将张贴与异步超时剪报

现在: 如何在Bash脚本中包含计时器?

链接的答案定义了一个'run_or_timeout'函数,以非常棒的方式去做你正在寻找的东西

 $ tail -f path |  sed / pattern / q

或者,如果要抑制不匹配行的输出:

 $ tail -f path |  sed -n'/ pattern / {p;  Q;}”

一个简单的方法来添加超时是做:

 $ cmd&sleep 10; 杀了$!  2> / dev / null

(抑制kill中的错误,以便如果进程在时间到期之前终止,则不会收到“无此进程”警告)。 请注意,这并不是健壮的,因为有可能cmd将终止,并且pid计数将环绕,并且一些其他命令在计时器到期时将具有该pid。

看看--max-count选项:

 tail -f file.log | grep -m 1 'PATTERN' 

它将在匹配PATTERN的第一行之后退出。


编辑 :注意@ Karoly的评论如下。 如果file.log速度较慢, grep进程可能会阻塞,直到在匹配行之后向文件添加其他内容为止。

 echo 'context PATTERN line' >> file.log ## grep shows the match but doesn't exit 

将打印匹配的行,但不会退出,直到附加内容被追加到文件(即使它还没有换行符):

 echo -n ' ' >> file.log ## Now the grep process exits 

在某些情况下(例如高速日志文件),这不是什么大问题,因为新的内容可能很快就会被添加到文件中。

另外请注意,当从控制台以标准输入读取时,这种行为不会发生,所以它看起来是grep从管道读取的方式上的差异:

 $ grep -m1 'PATTERN' - # manually type PATTERN and enter, exits immediately $ cat | grep -m1 'PATTERN' # manually type PATTERN and enter, and it hangs 

等待文件出现

 while [ ! -f /path/to/the.file ] do sleep 2; done 

等待文件中的字符串

 while ! grep "the line you're searching for" /path/to/the.file do sleep 10; done 

https://superuser.com/a/743693/129669

我有类似的要求,并提出以下。

你之后的单行是以“timeout ….”开始的行,其余的代码是为了提供单行所需的信息和事后清理所需的准备工作。

 ## ## Start up the process whose log file we want to monitor for a specific pattern. ## touch file_to_log_nohup_output.log nohup "some_command" "some_args" >> file_to_log_nohup_output.log 2>&1 & my_cmd_pid=$! ## Specify what our required timeout / pattern and log file to monitor is my_timeout=10m my_logfile="/path/to/some_command's/log/file.txt" my_pattern="Started all modules." ## How does this work? ## - In a bash sub shell, started in the background, we sleep for a second and ## then execute tail to monitor the application's log file. ## - Via the arguments passed to it, tail has been configured to exit if the ## process whose log file it is monitoring dies. ## - The above sub shell, is executed within another bash sub shell in which ## we identify the process id of the above sub shell and echo it to stdout. ## - Lastly, in that sub shell we wait for the sub shell with tail running in ## it as a child process, to terminate and if it does terminate, we redirect ## any output from its stderr stream to /dev/null. ## - The stdout output of the above sub shell is piped into another sub shell ## in which we setup a trap to watch for an EXIT event, use head -1 to read ## the process id of the tail sub shell and finally start a grep process ## to grep the stdout for the requested pattern. Grep will quit on the first ## match found. The EXIT trap will kill the process of the tail sub shell ## if the sub shell running grep quits. ## ## All of this is needed to tidy up the monitoring child processes for ## tail'ing + grep'ing the application log file. ## ## Logic of implementing the above sourced from: http://superuser.com/a/1052328 timeout ${my_timeout} bash -c '((sleep 1; exec tail -q -n 0 --pid=$0 -F "$1" 2> /dev/null) & echo $! ; wait $! 2>/dev/null ) | (trap "kill \${my_tail_pid} 2>/dev/null" EXIT; my_tail_pid="`head -1`"; grep -q "$2")' "${my_cmd_pid}" "${my_logfile}" "${my_pattern}" 2>/dev/null & ## ## We trap SIGINT (ie when someone presses ctrl+c) to clean up child processes. ## trap 'echo "Interrupt signal caught. Cleaning up child processes: [${my_timeout_pid} ${my_cmd_pid}]." >> "file_to_log_nohup_output.log"; kill ${my_timeout_pid} ${my_cmd_pid} 2> /dev/null' SIGINT wait ${my_timeout_pid} my_retval=$? trap - SIGINT ## If the time out expires, then 'timeout' will exit with status 124 otherwise ## it exits with the status of the executed command (which is grep in this ## case). if [ ${my_retval} -eq 124 ]; then echo "Waited for [${my_timeout}] and the [${my_pattern}] pattern was not encountered in application's log file." exit 1 else if [ ${my_retval} -ne 0 ]; then echo "An issue occurred whilst starting process. Check log files:" echo " * nohup output log file: [file_to_log_nohup_output.log]" echo " * application log file: [${my_logfile}]" echo " * application's console log file (if applicable)" exit 1 else info_msg "Success! Pattern was found." exit 0 fi fi 

我已经实现了上述到一个独立的脚本,可用于运行一个命令等待其日志文件具有所需的模式,超时。

这里可用: run_and_wait.sh