4、日志采集入门:文件采集(tail -f)、网络采集(Syslog)、Agent采集(Filebeat/Logstash)

日志检索这件事,地基就是采集。你想想看,后面再牛的检索分析,如果数据进不来或者进来就是脏的,那全白搭。这一章,咱们就把三种最主流的采集方式掰开揉碎讲清楚。

我个人习惯把采集分为三代:第一代是直接读文件,第二代是收网络流,第三代是专用 Agent。别觉得老方法就该淘汰,实际项目中往往是三代混着用。

核心观点:没有银弹。选哪种采集方式,取决于你的日志源头在哪、网络环境允不允许装 Agent、以及你对实时性的要求有多高。
日志采集三大方式 文件采集 tail -f / 轮询读取 网络采集 Syslog / TCP/UDP Agent采集 Filebeat / Logstash • 零依赖,SSH即可 • 适合临时排查 • 不支持多行日志 • 断点续传需自己实现 • 网络设备标配 • 集中式接收 • 无状态,易丢包 • 格式不统一 • 功能最全 • 支持过滤/转换 • 需安装维护 • 资源占用可控 实际项目:80% 场景用 Agent,15% 用 Syslog,5% 临时用 tail -f

4.1 文件采集:最朴素但最可靠

说白了就是读文件。Linux 下 tail -f 大家都会用,但生产环境里可没这么简单。我见过太多人直接用 tail -f 重定向到另一个文件,结果进程一挂,日志全丢。

文件采集的核心机制其实就两个:

  • 轮询(Polling):每隔几秒去检查文件有没有新内容。简单,但浪费 IO。
  • 通知(inotify/FSEvents):操作系统告诉你文件变了。高效,但实现复杂。

嗯,这里要注意:大部分生产工具用的是「轮询 + inotify 兜底」的策略。Filebeat 就是这么干的——优先用 inotify,如果内核不支持就回退到轮询。

我的经验:如果你只是临时排查问题,tail -f 完全够用。但要是做长期采集,一定要考虑「断点续传」。我曾经踩过一个坑:服务器重启后,采集脚本从文件头开始重新读,结果把几 GB 的历史日志又发了一遍,直接把下游的 Kafka 打挂了。

文件采集的典型场景:

  • 应用日志(Java 的 application.log、Nginx 的 access.log)
  • 系统日志(/var/log/messages、/var/log/syslog)
  • 容器日志(Docker 的 stdout/stderr 重定向文件)

4.2 网络采集:Syslog 的前世今生

Syslog 是个老古董了,1980 年代就有了。但你别小看它,网络设备、防火墙、路由器到现在还在用。说白了,它就是「设备把日志通过网络扔给你,你爱收不收」。

Syslog 的传输方式:

协议 端口 可靠性 适用场景
UDP 514 低(无确认) 内网、非关键日志
TCP 514 / 1468 中(有确认) 需要可靠传输
RELP 20514 / 2514 高(应用层确认) 关键业务日志

我个人建议:能用 TCP 就别用 UDP。UDP 虽然快,但丢包了你根本不知道。我曾经帮一个客户排查问题,发现他们的网络设备用 UDP 发 Syslog,高峰期丢包率超过 30%,但监控面板上一切正常——因为丢包了也不报错。

避坑指南:Syslog 的格式是个大坑。RFC 3164(老格式)和 RFC 5424(新格式)差异很大。很多设备厂商还自己加字段。你如果直接拿原始 Syslog 做检索,会发现时间戳格式五花八门。我建议统一用 Logstash 或 rsyslog 做一次格式标准化。

Syslog 的典型架构:

网络设备/服务器 
    ↓ UDP/TCP
Syslog 接收器(rsyslog/syslog-ng)
    ↓ 过滤/格式化
日志文件 或 直接转发到 Kafka/ES

4.3 Agent 采集:Filebeat 和 Logstash 怎么选?

这是目前最主流的方式。Agent 说白了就是一个轻量级程序,装在目标机器上,负责读日志、做简单处理、然后发走。

ELK 生态里两个主力:

  • Filebeat:轻量级采集器。Go 写的,资源占用极低。适合只做「采集 + 转发」。
  • Logstash:重量级处理器。Java 写的,功能强大但吃内存。适合做「采集 + 复杂处理 + 转换」。

我一般这么分:

对比维度 Filebeat Logstash
资源占用 低(10-50MB 内存) 高(256MB-1GB 内存)
处理能力 简单过滤(include/exclude) 复杂转换(grok、mutate、date)
输出插件 Elasticsearch、Logstash、Kafka 50+ 种输出
部署方式 DaemonSet / 二进制 独立服务 / 容器
典型用法 每台机器装一个 集中部署几台做处理

Filebeat 的配置其实很简单。我贴一个最常用的例子:

# filebeat.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/nginx/access.log
    - /var/log/nginx/error.log
  multiline:
    pattern: '^\d{4}-\d{2}-\d{2}'
    negate: true
    match: after

output.elasticsearch:
  hosts: ["http://elasticsearch:9200"]
  index: "nginx-%{+yyyy.MM.dd}"

嗯,这里有个关键点:multiline 配置。Java 异常栈、Python traceback 都是多行日志。如果不做 multiline 合并,一条异常会被拆成几十条记录,检索时根本没法看。我刚开始用 Filebeat 时就吃过这个亏,查了半天才发现是 multiline 没配。

最佳实践:Filebeat + Logstash 组合。Filebeat 负责采集和轻量过滤,Logstash 负责集中处理和转换。这样既保证了采集端的轻量,又保留了处理端的灵活性。

Logstash 的配置稍微复杂点,但功能确实强:

# logstash.conf
input {
  beats {
    port => 5044
  }
}

filter {
  grok {
    match => { "message" => "%{COMBINEDAPACHELOG}" }
  }
  date {
    match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
  }
  mutate {
    remove_field => [ "message" ]
  }
}

output {
  elasticsearch {
    hosts => ["http://elasticsearch:9200"]
    index => "weblog-%{+yyyy.MM.dd}"
  }
}

你看,Logstash 的 filter 可以做 grok 解析、时间戳转换、字段删除。这些在 Filebeat 里做不了,或者做起来很别扭。

4.4 三种方式怎么选?一张表说清楚

场景 推荐方式 理由
临时排查问题 tail -f 零部署,用完即走
网络设备日志 Syslog (TCP) 设备只支持 Syslog
应用日志(标准格式) Filebeat 轻量,够用
应用日志(需解析) Filebeat + Logstash 采集轻量,处理灵活
容器环境(K8s) Filebeat DaemonSet 官方支持,配置简单
高吞吐、低延迟 Filebeat + Kafka 削峰填谷,保证不丢
我的建议:刚开始做日志采集,别想一步到位。先用 Filebeat 把日志收进来,跑通了再慢慢加 Logstash 做处理。我见过太多团队一上来就上 Logstash,结果配置写了两周还没跑通,最后发现其实 Filebeat 默认配置就能满足 80% 的需求。

最后说一句:采集是日志检索的起点,但也是最容易被忽视的环节。你想想看,如果采集端就丢了数据、乱了格式,后面 Elasticsearch 再牛也救不回来。所以,花时间把采集搞扎实,值得。