跳转到内容
搜索 RunEntLinux 文档

仅搜索 RunEntLinux 通用文档,各发行版文档使用各自的搜索入口。

    浏览当前文档目录

    日志是排查问题、审计安全事件、分析系统行为的核心数据来源。本文介绍如何在 EL 系发行版上有效地管理和分析日志。

    在 CentOS/AlmaLinux/Rocky Linux 中,日志系统由两个核心组件构成:

    • journald(systemd-journald):systemd 的日志守护进程,收集所有 systemd 单元、内核和启动日志,存储为二进制格式
    • rsyslog:传统的 syslog 守护进程,接收 journald 转发的日志,写入文本文件,支持远程传输

    两者协同工作:journald 负责收集,rsyslog 负责持久化存储和转发。

    应用/服务 → journald(二进制日志)→ rsyslog → /var/log/下的文本日志
    ↓
    远程日志服务器
    Terminal window
    # 查看所有日志
    journalctl
    # 查看最新的日志(类似 tail -f)
    journalctl -f
    # 只看最近 100 行
    journalctl -n 100
    # 查看某个服务的日志
    journalctl -u nginx
    journalctl -u sshd -f
    # 查看内核日志
    journalctl -k
    # 按时间范围查看
    journalctl --since "2026-03-20 00:00:00" --until "2026-03-20 23:59:59"
    journalctl --since "1 hour ago"
    journalctl --since today
    # 按优先级过滤(0=emerg, 3=err, 4=warning, 6=info)
    journalctl -p err # 只看错误及以上
    journalctl -p warning -u nginx # nginx 的警告级别日志
    # 输出为 JSON 格式
    journalctl -u nginx -o json-pretty -n 5
    # 查看磁盘使用量
    journalctl --disk-usage

    默认情况下,journald 日志可能仅存储在内存中(/run/log/journal/),重启后丢失。开启持久化存储:

    Terminal window
    # 创建持久化目录
    sudo mkdir -p /var/log/journal
    sudo systemd-tmpfiles --create --prefix /var/log/journal
    # 编辑配置
    sudo tee /etc/systemd/journald.conf.d/persistent.conf > /dev/null <<'EOF'
    [Journal]
    Storage=persistent
    SystemMaxUse=2G
    SystemMaxFileSize=256M
    MaxRetentionSec=3month
    Compress=yes
    EOF
    # 重启 journald
    sudo systemctl restart systemd-journald

    关键参数说明:

    参数说明
    Storage=persistent持久化存储到磁盘
    SystemMaxUse=2G日志最多占用 2G 磁盘空间
    SystemMaxFileSize=256M单个日志文件最大 256M
    MaxRetentionSec=3month最多保留 3 个月
    Compress=yes启用压缩
    Terminal window
    # 查看 rsyslog 默认规则
    cat /etc/rsyslog.conf
    # EL 系默认的日志分布:
    # /var/log/messages - 大多数系统日志
    # /var/log/secure - 认证与授权日志
    # /var/log/maillog - 邮件日志
    # /var/log/cron - cron 任务日志
    # /var/log/boot.log - 启动日志
    Terminal window
    # 为特定程序创建独立的日志文件
    sudo tee /etc/rsyslog.d/myapp.conf > /dev/null <<'EOF'
    # 将 myapp 标签的日志写入独立文件
    if $programname == 'myapp' then /var/log/myapp.log
    & stop
    # 将所有 local6 设施的日志写入指定文件
    local6.* /var/log/custom-app.log
    EOF
    sudo systemctl restart rsyslog

    rsyslog 支持自定义日志格式:

    Terminal window
    sudo tee /etc/rsyslog.d/custom-template.conf > /dev/null <<'EOF'
    # 自定义日志格式模板
    template(name="CustomFormat" type="string"
    string="%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg%\n"
    )
    # 对特定日志应用自定义格式
    local6.* /var/log/custom-app.log;CustomFormat
    EOF

    在日志收集服务器上配置接收端:

    Terminal window
    sudo tee /etc/rsyslog.d/remote.conf > /dev/null <<'EOF'
    # 启用 TCP 接收(端口 514)
    module(load="imtcp")
    input(type="imtcp" port="514")
    # 按主机名分目录存储远程日志
    template(name="RemoteHost" type="string"
    string="/var/log/remote/%HOSTNAME%/%PROGRAMNAME%.log"
    )
    # 远程日志使用自定义存储路径
    if $fromhost-ip != '127.0.0.1' then {
    action(type="omfile" dynaFile="RemoteHost")
    stop
    }
    EOF
    sudo systemctl restart rsyslog
    # 防火墙放行
    sudo firewall-cmd --permanent --add-port=514/tcp
    sudo firewall-cmd --reload

    在客户端上配置日志转发:

    Terminal window
    sudo tee /etc/rsyslog.d/forward.conf > /dev/null <<'EOF'
    # 将所有日志通过 TCP 转发到远程服务器
    *.* @@log-server.example.com:514
    # @ 表示 UDP
    # @@ 表示 TCP(推荐,可靠性更高)
    # 如果远程不可用,启用磁盘缓冲队列
    action(
    type="omfwd"
    target="log-server.example.com"
    port="514"
    protocol="tcp"
    queue.type="LinkedList"
    queue.filename="forward_queue"
    queue.maxdiskspace="1g"
    queue.saveonshutdown="on"
    action.resumeRetryCount="-1"
    )
    EOF
    sudo systemctl restart rsyslog

    生产环境中,日志传输应当加密:

    Terminal window
    # 安装 TLS 模块
    sudo dnf install rsyslog-gnutls -y
    # 日志服务器端 TLS 配置
    sudo tee /etc/rsyslog.d/tls-server.conf > /dev/null <<'EOF'
    global(
    defaultNetstreamDriver="gtls"
    defaultNetstreamDriverCAFile="/etc/pki/rsyslog/ca.pem"
    defaultNetstreamDriverCertFile="/etc/pki/rsyslog/server-cert.pem"
    defaultNetstreamDriverKeyFile="/etc/pki/rsyslog/server-key.pem"
    )
    module(load="imtcp"
    StreamDriver.Name="gtls"
    StreamDriver.Mode="1"
    StreamDriver.AuthMode="x509/name"
    )
    input(type="imtcp" port="6514")
    EOF
    # 客户端 TLS 配置
    sudo tee /etc/rsyslog.d/tls-client.conf > /dev/null <<'EOF'
    global(
    defaultNetstreamDriver="gtls"
    defaultNetstreamDriverCAFile="/etc/pki/rsyslog/ca.pem"
    defaultNetstreamDriverCertFile="/etc/pki/rsyslog/client-cert.pem"
    defaultNetstreamDriverKeyFile="/etc/pki/rsyslog/client-key.pem"
    )
    action(
    type="omfwd"
    target="log-server.example.com"
    port="6514"
    protocol="tcp"
    StreamDriver="gtls"
    StreamDriverMode="1"
    StreamDriverAuthMode="x509/name"
    )
    EOF

    logrotate 防止日志文件无限增长,自动压缩和清理旧日志。

    Terminal window
    cat /etc/logrotate.conf
    # 默认设置:
    # - 每周轮转
    # - 保留 4 周
    # - 创建新文件
    # - 包含 /etc/logrotate.d/ 目录下的配置
    Terminal window
    sudo tee /etc/logrotate.d/myapp > /dev/null <<'EOF'
    /var/log/myapp.log
    /var/log/myapp-error.log
    {
    daily # 每天轮转
    missingok # 文件不存在不报错
    rotate 30 # 保留 30 份
    compress # gzip 压缩
    delaycompress # 延迟一次再压缩(便于程序继续写入)
    notifempty # 空文件不轮转
    create 0640 myapp myapp # 创建新文件的权限和属主
    dateext # 使用日期作为后缀(而非数字)
    dateformat -%Y%m%d # 日期格式
    sharedscripts # 多个文件只执行一次脚本
    postrotate
    # 轮转后通知应用重新打开日志文件
    /bin/kill -USR1 $(cat /var/run/myapp.pid 2>/dev/null) 2>/dev/null || true
    endscript
    }
    EOF
    Terminal window
    sudo tee /etc/logrotate.d/nginx > /dev/null <<'EOF'
    /var/log/nginx/*.log {
    daily
    missingok
    rotate 60
    compress
    delaycompress
    notifempty
    create 0640 nginx adm
    dateext
    sharedscripts
    postrotate
    [ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
    endscript
    }
    EOF
    Terminal window
    # 调试模式(不实际执行,只显示会做什么)
    sudo logrotate -d /etc/logrotate.d/myapp
    # 强制执行轮转
    sudo logrotate -f /etc/logrotate.d/myapp
    # 查看 logrotate 状态文件
    cat /var/lib/logrotate/logrotate.status
    Terminal window
    # 搜索错误信息
    grep -i "error" /var/log/messages
    grep -i "failed" /var/log/secure
    # 搜索特定时间段
    grep "Mar 20 1[0-5]:" /var/log/messages # 3月20日 10:00-15:59 的日志
    # 排除干扰信息
    grep -i "error" /var/log/messages | grep -v "No error"
    # 递归搜索目录
    grep -r "out of memory" /var/log/
    # 显示匹配行前后的上下文
    grep -B 3 -A 5 "kernel panic" /var/log/messages
    # 统计出现次数
    grep -c "Failed password" /var/log/secure
    Terminal window
    # 统计各 IP 的 SSH 失败登录次数
    awk '/Failed password/ {for(i=1;i<=NF;i++) if($i=="from") print $(i+1)}' /var/log/secure \
    | sort | uniq -c | sort -rn | head -20
    # 按小时统计 Nginx 请求数
    awk '{print $4}' /var/log/nginx/access.log \
    | cut -d: -f1-2 | sort | uniq -c
    # 统计 HTTP 状态码分布
    awk '{print $9}' /var/log/nginx/access.log \
    | sort | uniq -c | sort -rn
    # 找出请求最慢的 URL(假设响应时间在最后一列)
    awk '{print $NF, $7}' /var/log/nginx/access.log \
    | sort -rn | head -20
    # 统计每分钟请求量(找出流量高峰)
    awk '{print $4}' /var/log/nginx/access.log \
    | cut -d: -f1-3 | sort | uniq -c | sort -rn | head -10
    Terminal window
    # 提取特定时间段的日志(journalctl 格式)
    sed -n '/^Mar 20 14:00/,/^Mar 20 15:00/p' /var/log/messages
    # 实时监控并高亮关键字
    tail -f /var/log/messages | grep --color=auto -i "error\|warning\|fail"
    # 使用 last 查看登录记录
    last -20 # 最近 20 条登录记录
    lastb -20 # 最近 20 条失败登录
    last reboot # 重启记录
    # 使用 ausearch 搜索审计日志(需要 auditd)
    ausearch -m avc # SELinux 拒绝事件
    ausearch -k login_events # 按审计规则搜索
    /usr/local/bin/log_summary.sh
    #!/bin/bash
    # 每日日志摘要报告
    DATE=$(date -d yesterday '+%b %d')
    REPORT="/tmp/log_summary_$(date +%Y%m%d).txt"
    {
    echo "=========================================="
    echo " 日志摘要报告 - ${DATE}"
    echo "=========================================="
    echo ""
    echo "--- SSH 失败登录 TOP 10 ---"
    grep "${DATE}" /var/log/secure 2>/dev/null \
    | grep "Failed password" \
    | awk '{for(i=1;i<=NF;i++) if($i=="from") print $(i+1)}' \
    | sort | uniq -c | sort -rn | head -10
    echo ""
    echo "--- 错误日志统计 ---"
    echo "messages 中的 error: $(grep -ci "error" /var/log/messages 2>/dev/null || echo 0)"
    echo "secure 中的 failure: $(grep -ci "fail" /var/log/secure 2>/dev/null || echo 0)"
    echo ""
    echo "--- 磁盘空间告警 ---"
    df -h | awk 'NR>1 {gsub(/%/,"",$5); if($5+0>80) print $0}'
    echo ""
    echo "--- 最近重启记录 ---"
    last reboot | head -5
    echo ""
    echo "--- OOM Killer 事件 ---"
    grep -c "Out of memory" /var/log/messages 2>/dev/null || echo "0 次"
    } > "$REPORT"
    cat "$REPORT"
    # 可选:邮件发送
    # mail -s "日志摘要 ${DATE}" admin@example.com < "$REPORT"

    当服务器数量增多时,需要专门的日志平台进行统一收集、搜索和分析。

    ELK Stack(Elasticsearch + Logstash + Kibana)

    Section titled “ELK Stack(Elasticsearch + Logstash + Kibana)”

    ELK 是最流行的日志分析平台:

    • Elasticsearch:日志存储和搜索引擎
    • Logstash:日志收集和处理管道
    • Kibana:Web 可视化界面

    使用 Filebeat 作为轻量级日志采集器:

    Terminal window
    # 安装 Filebeat(下面固定 8.x 仓库;Elastic 9.x 已发布,8.x 的支持/EOL 状态请查 Elastic 官方 EOL 表后再决定是否跟 9.x)
    sudo rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
    sudo tee /etc/yum.repos.d/elastic.repo > /dev/null <<'EOF'
    [elastic-8.x]
    name=Elastic repository for 8.x packages
    baseurl=https://artifacts.elastic.co/packages/8.x/yum
    gpgcheck=1
    gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
    enabled=1
    autorefresh=1
    type=rpm-md
    EOF
    sudo dnf install filebeat -y
    # 配置 Filebeat 采集系统日志
    sudo tee /etc/filebeat/filebeat.yml > /dev/null <<'EOF'
    filebeat.inputs:
    - type: log
    enabled: true
    paths:
    - /var/log/messages
    - /var/log/secure
    fields:
    type: syslog
    - type: log
    enabled: true
    paths:
    - /var/log/nginx/access.log
    fields:
    type: nginx-access
    output.elasticsearch:
    hosts: ["https://elasticsearch:9200"]
    username: "elastic"
    password: "your_password"
    EOF
    sudo systemctl enable --now filebeat

    Loki 是 Grafana 推出的轻量级日志聚合系统,对标 ELK 但资源消耗更低。

    推荐做法:Grafana Alloy(采集器)+ Loki(存储/查询)

    Terminal window
    # 示例版本:Alloy v1.20.1、Loki v3.7.8(2026-10 核对;装前看 releases 页)
    cd /tmp
    curl -LO https://github.com/grafana/alloy/releases/download/v1.20.1/alloy-linux-amd64.zip
    unzip alloy-linux-amd64.zip && sudo cp alloy-linux-amd64 /usr/local/bin/alloy && sudo chmod +x /usr/local/bin/alloy

    Alloy 的最小采集配置(语法以官方 reference 为准):

    /etc/alloy/config.alloy
    loki.source.file "logs" {
    targets = [{ __path__ = "/var/log/*.log" }]
    forward_to = [loki.write.default.receiver]
    }
    loki.write "default" {
    endpoint { url = "http://127.0.0.1:3100/loki/api/v1/push" }
    }

    存量 Promtail(仅用于读懂旧配置,EOL 后不要再新装):

    Terminal window
    # 示例版本:Loki/Promtail 3.0.0(2024-04,历史示例)
    cd /tmp
    curl -LO https://github.com/grafana/loki/releases/download/v3.0.0/promtail-linux-amd64.zip
    unzip promtail-linux-amd64.zip
    sudo cp promtail-linux-amd64 /usr/local/bin/promtail
    sudo chmod +x /usr/local/bin/promtail
    # 基础配置
    sudo mkdir -p /etc/promtail
    sudo tee /etc/promtail/config.yml > /dev/null <<'EOF'
    server:
    http_listen_port: 9080
    positions:
    filename: /var/lib/promtail/positions.yaml
    clients:
    - url: http://loki-server:3100/loki/api/v1/push
    scrape_configs:
    - job_name: syslog
    static_configs:
    - targets:
    - localhost
    labels:
    job: syslog
    host: __HOSTNAME__
    __path__: /var/log/messages
    - job_name: nginx
    static_configs:
    - targets:
    - localhost
    labels:
    job: nginx
    host: __HOSTNAME__
    __path__: /var/log/nginx/*.log
    EOF
    # 替换主机名
    sudo sed -i "s/__HOSTNAME__/$(hostname)/" /etc/promtail/config.yml

    Loki 的优势在于它不索引日志全文,而是通过标签(labels)组织日志流,资源消耗远低于 Elasticsearch,非常适合中小规模部署。

    任务工具
    查看服务日志journalctl -u 服务名
    查看系统日志/var/log/messages 或 journalctl
    日志持久化journald Storage=persistent
    日志轮转logrotate
    远程集中收集rsyslog TCP/TLS 转发
    日志搜索分析grep / awk / journalctl 过滤
    大规模日志平台ELK Stack 或 Grafana Loki

    养成定期检查日志的习惯,并通过自动化脚本或日志平台及时发现异常,是保障服务器稳定运行的关键实践。