Linux:阻塞直到一个字符串在文件中匹配(“tail + grep with blocking”)

z0qdvdin  于 2023-08-03  发布在  Linux
关注(0)|答案(7)|浏览(101)

在bash/GNU工具中是否有一些单行的方法来阻止直到文件中有匹配的字符串?理想情况下,超时。我想避免多行循环。

**更新:**似乎我应该强调,我希望在字符串匹配时结束该过程。

htrmnn0y

htrmnn0y1#

感谢两人的回答,但重要的是,该过程块,直到找到,然后结束。我发现了这个:

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

字符串
-q的可移植性不是很好,但我只使用Red Hat Enterprise Linux,所以没问题。关于Timeout:

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

xcitsw88

xcitsw882#

我用sed而不是grep做了一个变体,打印所有解析的行。

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

字符串
脚本位于https://gist.github.com/2377029

8mmmxcuj

8mmmxcuj3#

看看--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


在某些情况下(例如高速日志文件),这不是什么大问题,因为新内容可能很快就会添加到文件中。
还要注意的是,当从控制台阅读作为stdin时,这个行为不会发生,所以它看起来与grep从管道读取的方式不同:

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

hs1ihplo

hs1ihplo4#

tail -f file | grep word | head -n1

字符串
将发布带有异步超时的snip
现在:如何在Bash脚本中包含计时器?
链接的答案定义了一个'run_or_timeout'函数,它以一种非常熟悉bash的方式执行您所要查找的操作

zf9nrax1

zf9nrax15#

$ tail -f path | sed /pattern/q

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

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


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

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


(禁止kill中的错误,这样如果进程在时间到期之前终止,您就不会收到“No such process”警告)。请注意,这一点也不健壮,因为cmd可能会终止,pid计数可能会绕回,并且在计时器到期时,其他一些命令将具有该pid。

cwtwac6a

cwtwac6a6#

等待文件出现

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

dojqjjoe

dojqjjoe7#

我有一个类似的要求,并提出了以下。
您所需要的一行程序是以“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 (i.e. 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

相关问题