Bash实时读取日志文件并在错误触发时执行命令的问题
Fixing Your Real-Time Error Log Detection Command
Let's break down why your original command isn't working as expected, then fix it properly.
The Problem With Your Original Command
Your command:
$(tail -n0 -f /Users/user/Desktop/file | grep error | echo 2 > /Users/user/Desktop/error.log) &
has two critical issues:
- The
echo 2runs unconditionally: Pipes in bash execute each command independently. Theecho 2doesn't wait for or react to the output ofgrep error— it just runs immediately when the command starts, which is why you always see a2written toerror.logright away, regardless of actual errors. - Unnecessary command substitution (
$(...)): Wrapping the whole pipeline in$(...)captures its output (which is nothing here) and tries to run it as a command. This adds no value and just complicates things.
The Fixed Solution
To only write 2 to error.log when a line containing "error" appears in your target log, use a loop that reacts to matching lines. Here's a reliable version:
tail -n0 -f /Users/user/Desktop/file | grep --line-buffered "error" | while read -r; do echo 2 >> /Users/user/Desktop/error.log done &
Or if you prefer a more concise one-liner:
tail -n0 -f /Users/user/Desktop/file | grep --line-buffered "error" | xargs -I {} echo 2 >> /Users/user/Desktop/error.log &
Key Details Explained
--line-buffered: By default,grepbuffers output when connected to a pipe, which means it might not send matching lines immediately. This flag forces it to flush output line-by-line, critical for real-time detection.while read -r: This loop runs every timegrepoutputs a matching line, triggering theecho 2only when an error is detected.>>instead of>: Using append (>>) ensures you don't overwrite existing entries inerror.logeach time an error is found. Use>only if you want to reset the log on each run.
Alternative: Using if with Grep's Exit Code
If you want to check for errors and write once per detection cycle (instead of once per error line), you could use this approach:
while true; do if tail -n0 -f /Users/user/Desktop/file | grep --line-buffered -q "error"; then echo 2 >> /Users/user/Desktop/error.log # Optional: Break here if you only want to detect the first error # break fi done &
The -q flag makes grep quiet (no output) and returns an exit code of 0 only if a match is found, which triggers the echo 2.
内容的提问来源于stack exchange,提问作者madsantos
相关产品推荐
相关产品推荐

