
如果你手头管着十几台服务器又经历过半夜被电话叫醒、一台台登录机器翻/var/log/messages找报错的日子大概能明白我为什么花了一个周末把 CentOS7 环境下的 rsyslog 日志服务器搭起来。这个组合我用了两年多rsyslog 负责采集、集中存储LogAnalyzer 负责在网页上检索和看报表资源占用极低维护成本几乎为零。这篇文章不是把官方文档翻译一遍而是把搭建过程中那些文档里不写、但真会让你卡住的细节都摊开讲清楚包括 journald 和 rsyslog 的边界、SELinux 和防火墙怎么放行、LogAnalyzer 的语言包怎么搞。适合谁看刚入门 Linux 运维的、中小团队想低成本搞集中日志的、以及被 ELK 折腾到怀疑人生想回归简单的人。1. 为什么我会在“日志时代”还选 rsyslog LogAnalyzer 这种组合1.1 一次凌晨两点的故障排查把我搞怕了事情起因是某台业务服务器磁盘告警我登录上去发现/var/log/messages已经被刷爆日志在系统层被截断。更麻烦的是那台机器之前跑过好几个服务日志散落在/var/log/下不同文件里我根本不知道到底哪个进程什么时候开始报错。那天凌晨我做了个决定与其每次故障都靠猜不如把日志集中收起来。当时团队没有专职运维也没有预算上商业日志平台所以选型要求就三条部署简单、能吃下内网所有服务器的 syslog、能有个网页让人查日志而不是每次都 ssh 上去 tail。1.2 rsyslog 在这个年代的不可替代性很多人一听到日志分析张嘴就是 ELK 或者 Loki。但你要清楚一点ELK 是分析平台不是采集工具而且 Elasticsearch 那套组件对内存的要求中小团队不一定吃得消。rsyslog 是系统自带的服务CentOS7 默认就装着不用额外引入 agent它对系统资源的占用几乎可以忽略。更重要的是rsyslog 的过滤规则和模板引擎处理网络设备、Linux 服务器的 syslog 非常成熟稳定跑了十几年。搭配 LogAnalyzer其实是用轻量方案解决“日志集中查看”这个基本诉求。我不否认 ELK 的检索能力强但你如果只是想让“各台机器日志落地到一个地方网页上能看能筛”rsyslog LogAnalyzer 一天就能上线还不会把服务器内存吃光。而且这套方案的链路很清晰客户端 rsyslog 把日志发到服务端的 514 端口服务端按客户端 IP 和日期分类写入文件LogAnalyzer 再读取这些文件供网页展示。1.3 整体架构先画个谱先说清楚整体流向后面配置才不会懵客户端系统日志 → journald 采集 → rsyslog 读取 → 发送到服务端 514 端口服务端rsyslog 监听 514 端口TCP/UDP→ 按来源 IP 和日期写入/data/logs/展示层Apache PHP 跑 LogAnalyzer → 读取/data/logs/下的日志文件 → 网页端检索和报表这里有个关键点要提前有概念CentOS7 默认有两个日志体系并存journald 负责采集二进制日志rsyslog 负责把日志转成文本写到传统文件里。我后面专门用一节讲它们的关系因为很多人就是栽在“journalctl 能看到日志但 /var/log/messages 没有内容”这种诡异问题上。2. 服务端落地接收端口、动态目录模板与 rsyslog 配置2.1 安装 rsyslog 和 rsyslog-mysql先看版本CentOS7 自带 rsyslog但保险起见我还是重新装了一遍并且建议你也确认下版本yum install -y rsyslog rsyslog-mysql rsyslogd -vCentOS7 自带的 rsyslog 一般是 8.x这个版本支持新版 RainerScript 脚本语法下面用的module(load...)、input(type...)、template(...)都是新语法如果你还在用老古董版本趁早升级。rsyslog-mysql这个包我先装了为什么因为我最初也纠结过要不要把日志写进 MySQL 方便 LogAnalyzer 查询后来发现文件模式完全够用多一个 MySQL 依赖反而是负担。但你如果强行要数据库模式这个包后面会用得到这里先装上没坏处。2.2 修改 /etc/rsyslog.conf开端口、加模板、分目录服务端的核心配置我直接给最终版然后再解释每一行的意图# 加载接收模块 module(loadimuxsock) # 本机系统日志 module(loadimklog) # 内核日志 module(loadimudp) # UDP接收 module(loadimtcp) # TCP接收 # 监听端口 input(typeimudp port514) input(typeimtcp port514) # 远程日志模板按来源IP / 日期 / 程序名 建目录和文件名 template(nameremote_logs typestring string/data/logs/%fromhost-ip%/%$year%-%$month%-%$day%/%programname%.log) # 将来自TCP/UDP的远程日志写入动态路径并停止继续处理 if ( $inputname imudp or $inputname imtcp ) then { action(typeomfile templateremote_logs dirCreateMode0755 fileCreateMode0644) stop }为什么同时开 TCP 和 UDP很多设备比如路由器、交换机、老牌网络设备只支持发 UDP syslog不开就收不到而 TCP 有确认机制重要业务的日志我建议走 TCP。把这两行都挂上等于兼容了所有场景代价仅是那点端口占用可以忽略。再说模板设计%fromhost-ip%是来源 IP%$year%-%$month%-%$day%是日期%programname%是日志标签。按 IP 分目录再按日期分文件是我测试过最实用的方案既方便快速定位某台机器某一天的日志归档时也只要打包对应日期目录就行。如果所有日志堆在一起到了要查的时候后悔都来不及。最后那个stop很重要它避免远程日志又走了一遍本地日志的默认规则被重复写入/var/log/messages否则日志量大的时候本地磁盘很快就会被刷满。改完配置文件先校验再重启rsyslogd -N1 systemctl restart rsyslog systemctl enable rsyslog ss -lntup | grep 514rsyslogd -N1是配置语法检查如果返回的结果里没有 error 说明配置没问题。ss能看到 514 端口在监听服务端这步就算成了。2.3 为什么日志目录要单独放 /data 而不是 /var我特意把日志写到/data/logs而不是/var/log这是经验教训。/var和系统根分区通常在一个磁盘分区上日志一旦爆炸直接把根分区写满系统会进入一种半瘫状态连 ssh 都登录不进去只能干瞪眼。而独立的/data分区即使写满最多就是日志服务报错系统核心功能不受影响。如果机器是虚拟机你可以单独挂一块数据盘给/data如果是物理机单独分一个区。这一步部署的时候多花十分钟关键时刻能救命。目录创建也很简单mkdir -p /data/logs即可rsyslog 的dirCreateMode参数会自动创建不存在的子目录权限也顺手帮你做好了。3. 客户端上报journald、rsyslog 和防火墙到底怎么配合3.1 journalctl 和 rsyslog 到底是不是一回事这是新手最好奇的问题也是排错最容易踩的坑。CentOS7 有两个日志体系同时在工作systemd-journald系统启动最早启动的服务之一把内核日志、系统服务日志以二进制格式存进/var/log/journal/用journalctl查看。rsyslog通过imjournal模块去读 journald 的数据然后按传统文本格式写到/var/log/messages、/var/log/secure等文件同时负责转发。所以你用journalctl -u nginx能看到 nginx 日志但/var/log/messages里未必有这完全正常因为 rsyslog 有自己的读取规则和过滤条件。理解了这层关系遇到“journalctl 有日志但 /var/log/messages 没有”的时候你就知道应该先去查 rsyslog 的 imjournal 配置而不是怀疑主机有问题。另外要记住journalctl查的是本机二进制日志它不会跨网络而 rsyslog 才是真正干转发事情的进程。我们做的日志服务器本质就是让每台客户端机器上的 rsyslog 把读取到的日志再往外发一份。3.2 客户端最小化配置一个终端搞定客户端配置比服务端简单得多在/etc/rsyslog.conf最末尾加一行即可# 把所有级别日志通过 TCP 发送到日志服务器 192.168.1.100 *.info;mail.none;authpriv.none;cron.none 192.168.1.100:514表示 TCP单个表示 UDP。我一般建议用 TCP因为日志丢失的话回头排查才是真痛苦。这行规则里的*.info表示 info 及以上级别都发排除了mail、authpriv、cron因为这些日志量大且对集中分析没意义尤其是 mail有邮件服务器的机器每天几千条纯粹浪费带宽和磁盘。如果你确实想收全也可以直接写*.* 192.168.1.100:514但我不推荐无用的日志只会让 LogAnalyzer 界面变得难用。改完同样要rsyslogd -N1 systemctl restart rsyslog客户端每台机器都执行一遍。量大有几十台机器的话建议你写成脚本配合 ansible 批量下发不然人工一台台敲太容易漏。3.3 防火墙与 SELinux日志收不到的第一嫌疑人很多人在客户端和服务端都配置好了但服务端就是收不到任何日志。十有八九是防火墙或 SELinux 拦了。CentOS7 默认防火墙是 firewalld如果你没有特殊优化514 端口默认是不放行的。需要在服务端执行firewall-cmd --permanent --add-port514/tcp firewall-cmd --permanent --add-port514/udp firewall-cmd --reload如果你的内网环境有固定网段我强烈建议别直接对所有来源开放用 rich rule 限定源地址更安全。这个放到安全加固那节细说这里先提到。SELinux 是另一个坑。CentOS7 默认 SELinux 是 Enforcingrsyslog 监听 514 这个标准端口通常没问题但如果你改了非标准端口SELinux 可能就会拦。另外 LogAnalyzer 要读/data/logs下的文件Apache 进程会被 SELinux 拦截这个我下一节专门讲。排查时先用getenforce看状态临时用setenforce 0测试是不是它的锅但千万别为了省事长期关闭生产环境关 SELinux 属于给自己埋雷。3.4 用 logger 和 tcpdump 验证数据真的到了配置完别急着部署 LogAnalyzer先验证链路通不通。在客户端执行logger -n 192.168.1.100 -P 514 -T test log from client-01然后在服务端看两件事/data/logs下有没有生成对应 IP 的目录目录里的日志文件有没有刚发过来的内容。如果文件没生成在服务端抓包看数据到底来没来tcpdump -i eth0 port 514 -nn这个命令能看到有没有数据包到达 514 端口。如果 tcpdump 有包但 rsyslog 没写文件问题基本就在 rsyslog 配置或 SELinux如果根本没包那就是防火墙或者客户端发送的问题。按照这个链路排查一般十分钟内就能定位。4. LogAnalyzer 部署中的真实坑PHP 版本、目录权限与数据源选择4.1 先装 LAMP 环境PHP 版本是个大坑LogAnalyzer 需要 Web 环境CentOS7 上最省事的就是 Apache PHP MariaDB。命令不复杂yum install -y httpd php php-mysql php-gd php-mbstring mariadb-server systemctl enable --now httpd mariadb这里有一个我踩过的坑CentOS7 系统源里的 PHP 版本是 5.4而新版 LogAnalyzer 对 PHP 版本有要求装完打开页面很可能白屏。我第一次部署就是卡在直接访问 IP 目录浏览器一片空白查 Apache 错误日志才发现 PHP 版本过老。解决办法是用 Remi 仓库装高版本 PHP操作如下yum install -y epel-release yum install -y http://rpms.remirepo.net/enterprise/remi-release-7.rpm yum install -y yum-utils yum-config-manager --enable remi-php74 yum install -y php php-mysql php-gd php-mbstring装完用php -v确认版本已经到 7.x 再继续。这个步骤文档里通常不会写但十个人部署有五个人会遇到提前做好能省很多时间。4.2 下载解压 LogAnalyzer注意 src 目录LogAnalyzer 在 SourceForge 上发布包名一般是loganalyzer-x.x.x.tar.gz。下载解压到 Web 目录cd /usr/local/src wget https://sourceforge.net/projects/loganalyzer/files/loganalyzer/4.1.13/loganalyzer-4.1.13.tar.gz tar zxf loganalyzer-4.1.13.tar.gz mkdir -p /var/www/html/loganalyzer cp -a loganalyzer-4.1.13/src/* /var/www/html/loganalyzer/ cd /var/www/html/loganalyzer touch config.php chmod 666 config.php注意源码包解压出来会有一个src目录真正的程序文件都在里面必须把src下的内容复制到站点根目录而不是把整个目录搬过去。config.php是安装向导要写的配置文件需要提前创建并给写权限否则向导会在检查环境那一步报错。这些细节点不试几次根本发现不了。4.3 安装向导数据源到底选 File 还是 MySQL打开浏览器访问http://服务器IP/loganalyzer/进入安装向导。向导会一步步检查目录权限、PHP 扩展然后让你配置日志数据源。这里是最需要想清楚的地方LogAnalyzer 支持两种数据源一种是直接读日志文件File一种是从 MySQL 数据库读日志。由于我们的 rsyslog 配置是把日志写入文件的所以选 File 即可完全不需要 MySQL。但如果你当初配了 rsyslog-mysql 并且把日志写库了那就选 MySQL。我的建议是中小规模、单机日志量不超过每天几 GB 的场景File 模式足够少一层数据库依赖少一个需要维护的组件查询速度也不差。File 模式的配置页里会让你填日志文件路径你可以填具体文件比如/data/logs/192.168.1.105/2024-01-01/nginx.log也可以填目录让 LogAnalyzer 去扫描。实际用下来LogAnalyzer 对“目录下新增文件”的自动发现能力一般所以 rsyslog 的模板设计最好把文件名固定下来让每台机器的日志文件结构一致这样维护成本最低。4.4 Apache 目录权限与 SELinuxLogAnalyzer 读不到日志的真相File 模式下配置好路径进入页面却看不到日志内容这是最常见的故障。排第一的原因是 Apache 的运行用户是apache它对/data/logs没有读权限。检查并授权ls -ld /data/logs chown -R apache:apache /data/logs排第二的原因是 SELinux。Apache 默认只能读/var/www下的内容你要让它在/data/logs下读取文件必须更新文件的安全上下文chcon -R -t httpd_sys_content_t /data/logs如果你的/data/logs目录还会继续由 rsyslog 写入用chcon而不是chown可能会导致 rsyslog 写入时被 SELinux 拒绝那就再给 rsyslog 的设置补一条。更稳妥的办法是用semanage把整个目录类型改成httpd_sys_content_t但这需要评估你本机的 SELinux 策略。总之记住一个排查思路先setenforce 0测试如果关掉 SELinux 就能读那就是安全上下文的问题别瞎调系统权限。5. 切换中文与让日志界面真正能“用起来”的细节5.1 LogAnalyzer 切换中文的正确姿势用 LogAnalyzer 看英文日志其实没什么障碍但给团队里其他同事用中文界面友好度完全不一样。LogAnalyzer 在安装完成后默认语言是英文。登录后台进入“Admin Center”在“General”选项卡里找到“Language”下拉框如果列表里有 Chinese 或 zh_CN直接选中保存就行。但很多版本的下拉框里根本没有中文选项因为官方发布包没有内置完整中文语言包。这个时候就需要手动补语言包去网上找一份zh_cn.php一个 PHP 语言文件把它放到/var/www/html/loganalyzer/include/lang/目录下然后回到页面刷新语言列表里就会多出中文选项。如果你实在找不到现成语言包还有一个笨办法复制一份en.php改名为zh_cn.php对照英文翻译成中文其实就是把$lang[xxx] xxx;数组里的值翻译一遍。这个文件信息量不小不建议纯手写有现成的就优先用现成的。需要注意中文界面容易出现乱码尤其是日志内容本身含中文时。解决方法是在服务端和客户端的 locale 环境里统一用 UTF-8并且 PHP 要装上 mbstring 扩展前面装环境的时候已经装过了。如果页面还是乱码检查/etc/locale.conf里的LANGen_US.UTF-8或zh_CN.UTF-8然后重启 httpd 和 rsyslog。5.2 LogAnalyzer 里怎么快速定位问题日志LogAnalyzer 的核心功能不是“看日志”而是“筛日志”。登录后首页会显示日志文件列表选中一个文件你会看到类似表格的日志信息包含时间、主机名、程序名、消息内容。顶部有查询框可以按时间段、主机、严重级别过滤。我实际用得最多的场景是某台机器半夜报错我先按主机 IP 筛出来再按时间范围缩小最后看 programname 定位是哪一个服务。这个操作比 ssh 上去grep快太多尤其是几十台机器同时查一个问题的时候。另外 LogAnalyzer 支持创建报表可以把每天的日志量、错误级别统计做成图表虽然比不了 Grafana 那种炫酷但胜在零配置、开箱即用。我的建议是别一上来就想搞高大上的图表先把“查日志”这件事做到位工具的价值就体现出来了。5.3 用户权限给同事开个只读账号LogAnalyzer 默认有一个 admin 账号安装向导会让你设置密码。如果给多个同事使用千万别共享 admin 账号原因不用多说。在 Admin Center 的 Users 菜单里可以创建新用户并且可以控制用户是否能修改系统配置。给普通同事开只读账号既能保证安全也避免有人误改配置导致整个日志系统挂掉。权限设置界面很直白用户名、密码、权限类型管理员/普通用户就这三样没有更细的粒度这也是 LogAnalyzer 这个轻量工具的特性能接受就留着不能接受只能上更重的平台。6. 上线后收不到日志我的排错链路与存储规划6.1 从客户端到页面一条链路逐步排查这套架构跑一段时间后最常见的故障就是“某台机器在 LogAnalyzer 上看不到日志了”。我的排查顺序是固定的按这个顺序通常几分钟就能定位先看客户端 rsyslog 是否还活着systemctl status rsyslog再看客户端能否解析日志服务器域名如果配的是 IP 通常没问题服务端看端口监听ss -lntup | grep 514服务端看防火墙规则firewall-cmd --list-all服务端看/data/logs下对应 IP 目录有没有新文件生成最后看 LogAnalyzer 数据源配置的路径和文件权限这个顺序的核心逻辑是沿着数据流走链路比对哪个环节断了就处理哪个环节。很多人一上来就改 rsyslog 配置结果问题出在防火墙白折腾。还有一个小技巧在客户端用logger -n 服务器IP -P 514 -T test $(date)发一条带时间戳的测试日志然后在服务端tail -f /data/logs/*/当天日期/*.log观察链路通不通一目了然。6.2 日志轮转配置别让磁盘被默默写满rsyslog 服务端把日志写到/data/logs后系统自带的 logrotate 不会管这个目录。如果不做日志轮转磁盘迟早会被写满——这不是危言耸听日志量大的环境一周就能写出几十 GB。我自建了一个 logrotate 配置/etc/logrotate.d/remote-logs/data/logs/*/*.log { daily rotate 30 compress delaycompress missingok notifempty copytruncate }解释下每个参数的意义daily每天轮转一次rotate 30保留 30 个压缩文件也就是大约一个月的日志compress把旧日志压缩成 gzdelaycompress表示延迟到下次轮转再压缩避免最近一天的日志文件还在被写就压缩导致数据冲突最关键的是copytruncate——因为 rsyslog 进程一直持有日志文件的句柄如果不加这个参数logrotate 把文件改名后 rsyslog 都感知不到还在往旧文件里写新文件永远是空的。用copytruncate让 logrotate 先复制内容再清空原文件rsyslog 写句柄不受影响这是最稳妥的做法。注意这个配置只覆盖/data/logs下的日志系统自身的/var/log/messages轮转由/etc/logrotate.d/syslog负责两者互不干扰。6.3 磁盘容量估算别等满了才想起来规划关于日志文件要占多少磁盘我提供一个估算公式便于你提前给/data分区规划大小。假设单台服务器平均每秒产生 20 条日志每条日志约 0.5KB那么一天的数据量大概是20 条/秒 × 0.5KB × 86400 秒 ≈ 864MB约 0.84GB。十台服务器就是 8.4GB/天按保留 30 天算需要 250GB 左右的可用空间。这个量级对绝大多数场景是够用的但如果你的应用疯狂打错误日志日志量可能会翻好几倍所以建议把轮转周期和保留天数一开始就定好并且给/data分区留出 20% 的余量。我见过不少事故都是日志量超预期、磁盘毫无征兆写满导致的本意是记日志防故障结果日志本身成了故障源。6.4 安全加固日志服务器也要关好门日志服务器上汇聚了所有机器的日志安全级别不亚于堡垒机。最基础的做法是防火墙只放行内网网段的 514 端口而不是对全网开放firewall-cmd --permanent --add-rich-rulerule familyipv4 source address192.168.1.0/24 port protocoltcp port514 accept firewall-cmd --permanent --add-rich-rulerule familyipv4 source address192.168.1.0/24 port protocoludp port514 accept firewall-cmd --reload如果公司没有严格的合规要求内网环境做这个级别的限制足够了。如果要跨机房传输日志建议上 rsyslog 的 TLS 加密rsyslog 8.x 原生支持 imtls 模块配置证书后可以让客户端和服务端之间的通道加密防止日志内容在网络上被截获。这个配置稍微复杂点但生产环境值得做。另外日志服务器的系统本身要及时打补丁/data分区做好监控磁盘使用率超过 80% 就告警——这些都属于运维基本功但在日志服务器上尤其重要因为它是排障的第一手信息来源。这套方案到今天依然是我处理内网日志的首选。它的定位很明确不是要去替代大数据分析平台而是用最低的成本解决“日志集中存储和查询”这个问题。最后顺手分享一个我自己的习惯每台新服务器装完系统第一件事就是配置 rsyslog 客户端、NTP 时间同步再写进自动化脚本。日志系统最怕的不是配置复杂而是你平时想不起来它出了事才后悔当初没关好。时间同步也务必做好客户端和服务端时间差太大会导致日志时间线错乱排查问题的时候会把方向带偏。