实时跟踪日志与流式告警
实时跟踪并筛选日志流,在错误模式出现的瞬间触发告警。
实时跟踪日志与流式告警 是 CoddyKit 上的免费 Linux Command Line & Bash Scripting Mastery 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Linux Command Line & Bash Scripting Mastery 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Linux Command Line & Bash Scripting Mastery 课程共包含 4 节课。
实时跟踪日志为何重要
在生产系统中,日志文件会持续增长。等到有人报告问题后才检查日志,意味着停机损失已经发生。实时日志跟踪可以让您在事件写入的瞬间观察其发生过程,从而立即响应故障、安全事件和性能下降。
- Web 服务器每个请求写入一行日志 — 错误会立即出现
- 应用程序守护进程会在异常触发的瞬间记录堆栈跟踪
- 身份验证系统会实时记录登录失败尝试
Unix 中用于此目的的基础工具是 tail -f,结合筛选和告警工具,可以将原始日志流转换为可采取行动的信号。
tail -f:跟踪实时日志
tail -f(跟踪)会保持文件打开,并在新行追加时将其打印出来。这是最简单、最普遍可用的实时日志工具。
常见用法:
tail -f /var/log/syslog— 跟踪系统日志tail -n 50 -f app.log— 显示最后 50 行,然后继续跟踪tail -f /var/log/nginx/access.log— 实时跟踪 nginx 请求
按 Ctrl+C 停止。除非您取消操作或终端关闭,否则该进程会一直保持连接。
#!/usr/bin/env bash
# Simulate a live log and follow it
LOGFILE='/tmp/demo_app.log'
# Write a header
echo '[INFO] Application started' >> "$LOGFILE"
# In a real scenario you would run:
# tail -f "$LOGFILE"
# Below we demonstrate tail showing the last 3 lines then exit
tail -n 3 "$LOGFILE"tail -F:应对日志轮换
许多系统会在午夜或日志文件达到大小限制时轮换日志文件。发生这种情况时,原文件会被重命名(例如 app.log.1),并创建新的 app.log。使用 tail -f 时,您会悄悄地继续读取旧的重命名文件,从而错过所有新的输出。
tail -F(大写 F)通过监视文件名而不是文件描述符解决了这个问题。当文件消失后重新出现时,tail -F 会自动重新打开它并继续跟踪。
- 在生产脚本中,应始终优先使用
tail -F,而不是tail -f - 适用于会轮换文件的 logrotate、newsyslog 和 Docker 日志驱动程序
# Follow nginx access log, surviving log rotation
tail -F /var/log/nginx/access.log
# Follow multiple files simultaneously
tail -F /var/log/nginx/access.log /var/log/nginx/error.log使用 grep 筛选日志流
直接跟踪繁忙的日志会让人难以应付 — 活跃的 Web 服务器每秒可能写入数百行。将 tail -F 的输出通过管道传给 grep,即可只保留您关注的模式。
流式 grep 的关键选项:
--line-buffered— 立即刷新每个匹配行,而不是进行缓冲;在流水线中必须使用,否则输出可能延迟或丢失-i— 不区分大小写地匹配-E— 使用扩展正则表达式进行交替匹配(error|warn|crit)-v— 反向匹配(排除行)
# Show only ERROR and WARN lines from a live application log
tail -F /var/log/myapp/app.log | grep --line-buffered -Ei 'error|warn|critical'
# Follow nginx and exclude health-check requests
tail -F /var/log/nginx/access.log | grep --line-buffered -v '/health'使用 awk 添加时间戳和上下文
日志行有时缺少有助于初步排查的上下文。您可以使用 awk 实时丰富日志流 — 添加本地时间戳、提取字段,或重新格式化输出以提高可读性。
通过管道使用时,awk 也会以流式(按行缓冲)模式运行,因此无需额外选项即可安全地用于实时流水线。
# Prepend a reception timestamp to every ERROR line
tail -F /var/log/myapp/app.log | \
grep --line-buffered -i 'error' | \
awk '{ print strftime("[%Y-%m-%d %H:%M:%S]"), $0; fflush() }'
# Extract HTTP status code (field 9) and URL (field 7) from nginx combined log
tail -F /var/log/nginx/access.log | \
awk '{ print $9, $7; fflush() }' | \
grep --line-buffered '^5'使用 Slack Webhook 发送告警
筛选只是工作的一半 — 检测到错误模式后,您还需要通知相关人员。Slack 入站 Webhook 只需调用一次 curl,就能向频道 POST 一条消息;除了 Webhook URL 外,不需要 Slack SDK 或其他凭据。
处理模式是:筛选日志流,并为每个匹配行发送一次 HTTP POST。
#!/usr/bin/env bash
# Real-time alert: send every ERROR line to a Slack channel
LOGFILE='/var/log/myapp/app.log'
WEBHOOK_URL='https://hooks.slack.com/services/T000/B000/XXXX'
tail -F "$LOGFILE" | grep --line-buffered -i 'error' | while IFS= read -r line; do
payload=$(printf '{"text":"*[ERROR ALERT]*\n%s"}' "$line")
curl -s -o /dev/null -X POST -H 'Content-Type: application/json' \
-d "$payload" "$WEBHOOK_URL"
done限制告警频率,避免噪声
日志风暴每分钟可能产生数千行错误。每行发送一条 Slack 消息会淹没频道,并导致告警疲劳。您需要限制频率 — 触发一次告警后,在冷却期间抑制后续通知。
这可以通过一个简单的时间戳文件实现:记录上次发送告警的时间;如果冷却时间尚未结束,则跳过本次触发。
#!/usr/bin/env bash
# Alert on ERROR lines but no more than once every 60 seconds
LOGFILE='/var/log/myapp/app.log'
WEBHOOK_URL='https://hooks.slack.com/services/T000/B000/XXXX'
COOLDOWN=60
LAST_ALERT_FILE='/tmp/last_alert_ts'
tail -F "$LOGFILE" | grep --line-buffered -i 'error' | while IFS= read -r line; do
now=$(date +%s)
last=0
[ -f "$LAST_ALERT_FILE" ] && last=$(cat "$LAST_ALERT_FILE")
if (( now - last >= COOLDOWN )); then
echo "$now" > "$LAST_ALERT_FILE"
payload=$(printf '{"text":"*[ERROR ALERT]*\n%s"}' "$line")
curl -s -o /dev/null -X POST -H 'Content-Type: application/json' \
-d "$payload" "$WEBHOOK_URL"
echo "[$(date)] Alert sent: $line"
else
echo "[$(date)] Suppressed (cooldown): $line"
fi
done使用滑动窗口统计错误突发
有时单行错误并不重要 — 但 30 秒内出现 20 个错误就是严重问题。滑动窗口计数器可以仅在错误速率超过阈值时触发告警,从而减少误报。
该技术会将每个匹配事件的纪元时间戳存储在临时文件中,然后统计落在窗口内的事件数量,再决定是否发送告警。
#!/usr/bin/env bash
# Alert when more than 10 errors occur within any 60-second window
LOGFILE='/var/log/myapp/app.log'
WINDOW=60
THRESHOLD=10
TS_FILE='/tmp/error_timestamps'
WEBHOOK_URL='https://hooks.slack.com/services/T000/B000/XXXX'
tail -F "$LOGFILE" | grep --line-buffered -i 'error' | while IFS= read -r line; do
now=$(date +%s)
echo "$now" >> "$TS_FILE"
# Keep only timestamps within the window
cutoff=$(( now - WINDOW ))
tmp=$(mktemp)
awk -v c="$cutoff" '$1 > c' "$TS_FILE" > "$tmp" && mv "$tmp" "$TS_FILE"
count=$(wc -l < "$TS_FILE")
if (( count > THRESHOLD )); then
msg="*[BURST ALERT]* ${count} errors in ${WINDOW}s — last: ${line}"
curl -s -o /dev/null -X POST -H 'Content-Type: application/json' \
-d "{\"text\":\"$msg\"}" "$WEBHOOK_URL"
# Clear to avoid re-alerting until next burst
> "$TS_FILE"
fi
donejournalctl -f:跟踪 systemd 日志
在现代 Linux 系统(RHEL、Ubuntu 20.04 及更高版本、Debian 10 及更高版本)中,服务会写入 systemd 日志,而不是普通文本文件。journalctl -f 相当于用于日志的 tail -F。
实用选项:
-u myapp.service— 仅跟踪指定单元-p err— 按优先级筛选(emerg、alert、crit、err、warning、notice、info、debug)--since '5 min ago'— 从相对时间点开始-o json— 输出结构化 JSON,供机器解析
# Follow only error-and-above entries for nginx
journalctl -f -u nginx.service -p err
# Stream journal as JSON and extract MESSAGE field with jq
journalctl -f -u myapp.service -o json | \
jq --unbuffered -r 'select(.PRIORITY <= "3") | .MESSAGE'multitail 与彩色多源监控
当您需要同时监视多个日志源时,multitail 会将终端分割成多个窗格 — 每个窗格跟踪不同的文件或命令,并可根据模式使用不同颜色。
如果尚未安装 multitail,一种轻量的纯 BASH 替代方案是为每个日志流添加源名称前缀,然后将它们合并到一个视图中。
# multitail: watch nginx access + error + app log in split panes
# (requires: apt install multitail or brew install multitail)
multitail /var/log/nginx/access.log /var/log/nginx/error.log /var/log/myapp/app.log
# Pure-Bash alternative — merge three streams with labeled prefixes
(
tail -F /var/log/nginx/access.log | sed --unbuffered 's/^/[nginx-access] /' &
tail -F /var/log/nginx/error.log | sed --unbuffered 's/^/[nginx-error] /' &
tail -F /var/log/myapp/app.log | sed --unbuffered 's/^/[myapp] /' &
wait
)构建自包含的告警守护进程
综合本课程所学内容,一个适用于生产环境的告警守护进程应当:
- 使用
tail -F稳健地跟踪日志文件 - 使用带缓冲的
grep筛选关键模式 - 限制通知频率,避免告警疲劳
- 记录自身活动,以便审计已发送的内容
- 作为由 systemd 或监管进程管理的后台进程运行
下面的脚本是一个最小但完整的守护进程,您可以将其放入 /usr/local/bin/,并通过 systemd 管理。
#!/usr/bin/env bash
# log_alert_daemon.sh — tail a log and fire Slack alerts with cooldown
set -euo pipefail
LOGFILE=${1:-'/var/log/myapp/app.log'}
PATTERN=${2:-'error|critical|fatal'}
WEBHOOK_URL=${SLACK_WEBHOOK_URL:?'Set SLACK_WEBHOOK_URL env var'}
COOLDOWN=${ALERT_COOLDOWN:-120}
DAEMON_LOG='/var/log/log_alert_daemon.log'
LAST_SENT_FILE='/tmp/log_alert_last_sent'
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$DAEMON_LOG"; }
log "Starting alert daemon: watching $LOGFILE for pattern: $PATTERN"
tail -F "$LOGFILE" | grep --line-buffered -Ei "$PATTERN" | while IFS= read -r line; do
now=$(date +%s)
last=0
[ -f "$LAST_SENT_FILE" ] && last=$(cat "$LAST_SENT_FILE")
if (( now - last >= COOLDOWN )); then
echo "$now" > "$LAST_SENT_FILE"
msg=$(printf '{"text":"*[ALERT]* %s\n%s"}' "$(hostname)" "$line")
if curl -s -o /dev/null -w '%{http_code}' -X POST \
-H 'Content-Type: application/json' -d "$msg" "$WEBHOOK_URL" | grep -q '^200$'; then
log "Alert sent: $line"
else
log "Alert FAILED to send: $line"
fi
else
log "Suppressed (cooldown ${COOLDOWN}s): $line"
fi
done知识检查:流式日志流水线
测试您对实时日志跟踪和流式告警的理解。
一个 BASH 流水线跟踪日志文件,并为每个匹配行发送 Slack 告警。日志风暴期间,10 秒内写入了 3,000 行错误。哪一项单独的更改最能防止脚本向 Slack 频道发送 3,000 条消息?
课程回顾:实时日志跟踪与流式告警
在本课程中,您从基本原理出发,构建了一套完整的实时日志可观测性流水线:
- tail -F 按名称跟踪日志文件,即使日志轮换也能继续工作 — 在生产环境中始终优先使用它,而不是
tail -f - grep --line-buffered 筛选实时流,同时不会引入延迟;在通过管道使用 grep 的命令中始终添加此选项
- 使用 fflush() 的 awk 以适合流式处理的方式为每行添加时间戳或提取字段
- 通过 curl 使用 Slack Webhook,通过单个 HTTP POST 发送告警 — 不需要 SDK
- 冷却文件通过强制规定通知之间的最短间隔,避免日志风暴期间产生告警疲劳
- 滑动窗口计数器检测错误突发(基于速率的告警),而不是对每一行单独作出反应
- journalctl -f 是 systemd 原生的 tail -F 替代方案,内置优先级筛选和 JSON 输出
- 自包含的告警守护进程脚本组合了所有这些模式,并可由 systemd 管理,以确保生产环境的可靠性
这些基本工具共同构成了任何自定义可观测性流水线的基础 — 不需要第三方代理。
常见问题解答
「实时跟踪日志与流式告警」课时是免费的吗?
是的 — 「实时跟踪日志与流式告警」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Linux Command Line & Bash Scripting Mastery 课程的其余内容,请升级到 CoddyKit PRO。 Linux Command Line & Bash Scripting Mastery 课程共包含 4 节课。
「实时跟踪日志与流式告警」这节课中我会学到什么?
实时跟踪并筛选日志流,在错误模式出现的瞬间触发告警。 你通过在浏览器中直接运行的动手代码来练习 Linux Command Line & Bash Scripting Mastery,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Linux Command Line & Bash Scripting Mastery 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Linux Command Line & Bash Scripting Mastery 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「实时跟踪日志与流式告警」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Linux Command Line & Bash Scripting Mastery 课中编写并运行代码吗?
能。每节 Linux Command Line & Bash Scripting Mastery 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。