创建rsyslog服务器接收nginx日志

参考:Docker 日志整合 syslog - 简书 (jianshu.com)

创建rsyslog容器

配置文件 rsyslog.conf

# /etc/rsyslog.conf configuration file for rsyslog
#
# For more information install rsyslog-doc and see
# /usr/share/doc/rsyslog-doc/html/configuration/index.html
#
# Default logging rules can be found in /etc/rsyslog.d/50-default.conf

#################
#### MODULES ####
#################

module(load="imuxsock") # provides support for local system logging
#module(load="immark")  # provides --MARK-- message capability

# provides UDP syslog reception
#若启用UDP进行传输,则取消下面两行的注释
#module(load="imudp")
#input(type="imudp" port="514")

# provides TCP syslog reception
#若启用TCP进行传输,则取消下面两行的注释
#module(load="imtcp")
#input(type="imtcp" port="514")

# provides kernel logging support and enable non-kernel klog messages
module(load="imklog" permitnonkernelfacility="on")

###########################
#### GLOBAL DIRECTIVES ####
###########################

#
# Use traditional timestamp format.
# To enable high precision timestamps, comment out the following line.
#
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat

# Filter duplicated messages
$RepeatedMsgReduction on

#
# Set the default permissions for all log files.
#
$FileOwner syslog
$FileGroup adm
$FileCreateMode 0640
$DirCreateMode 0755
$Umask 0022
$PrivDropToUser syslog
$PrivDropToGroup syslog

#
# Where to place spool and state files
#
$WorkDirectory /var/spool/rsyslog

#
# Include all config files in /etc/rsyslog.d/
#
$IncludeConfig /etc/rsyslog.d/*.conf

Dockerfile

FROM ubuntu:20.04
 
# 设置环境变量
ENV DEBIAN_FRONTEND=noninteractive
 
# 更新包列表并安装 rsyslog
RUN apt-get update && \
    apt-get install -y rsyslog && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*
# 启动 rsyslog 服务
CMD ["rsyslogd", "-n"]

docker-compose.yml

version: '3.8'

services:
  rsyslog:
    build: .
    container_name: my-rsyslog-container
    ports:
      - "514:514/udp"
      - "514:514/tcp"  #  根据配置文件开放的端口和协议
    volumes:
      - ./path/to/your/log-dir:/var/log #挂载接收到的数据
      - ./rsyslog.conf:/etc/rsyslog.conf  # 挂载宿主机的 rsyslog.conf 根据配置位置修改
    restart: unless-stopped

docker-compose启动

sudo docker-compose up --build -d

测试rsyslog服务器启动


#打开终端并运行以下命令:
sudo docker inspect my-rsyslog-container|grep "IP" #查看容器IP
#发送 UDP 日志 这里IP修改成容器IP
logger -n 172.17.0.6 -P 514 "This is a test log message over UDP"
#发送 TCP 日志
logger -n 172.17.0.6 -P 514 -T "This is a test log message over TCP"
#进入容器并查看日志文件来验证是否成功接收到日志。
sudo docker exec -it my-rsyslog-container sh
 
#cat /var/log/syslog
#检查 /var/log/syslog 文件中是否包含您发送的日志消息。如果一切正常,您应该能看到类似于以下内容的输出:
This is a test log message over UDP
 

日志转发到rsyslog服务器

参考:Docker 日志整合 syslog - 简书 (jianshu.com)

方法一:利用Docker容器日志连接

下面启动容器,指定使用 syslog:

# 先删除之前的容器
$ docker stop nginx
$ docker rm nginx

# 启动
$ docker run \
    -d \
    -p 80:80 \
    --name nginx \
    --log-driver syslog \
    --log-opt syslog-address=tcp://localhost:514 \
    nginx

#进入容器并查看日志文件来验证是否成功接收到日志。
sudo docker exec -it my-rsyslog-container sh

$cat /var/log/all.log 或
$ tail -f /var/log/syslog

如果系统中启动了多个容器,每个容器的日志都输出到 syslog,就比较混乱了,这时我们可以在日志中指定容器tag,从而方便识别出相应的日志。

$ docker run \
    -d \
    -p 80:80 \
    --name nginx \
    --log-driver syslog \
    --log-opt syslog-address=tcp://localhost:514 \
    --log-opt tag="nginx" \
    nginx 

tag还可以更精确一点,因为docker提供了丰富的模板标签:

{{.ID}}:容器ID的前12个字符
{{.FullID}}:容器ID的完整名称
{{.Name}}:容器名称
{{.ImageID}}:容器镜像ID的前12个字符
{{.ImageFullID}}:容器镜像ID的完整名称
{{.ImageName}}:容器镜像名称
{{.DaemonName}}:Docker守护进程名称(名为docker)
示例:


$ docker run \
    -d \
    -p 80:80 \
    --name nginx \
    --log-driver syslog \
    --log-opt syslog-address=tcp://localhost:514 \
    --log-opt tag="{{.ImageName}}/{{.Name}}/{{.ID}}" \
    nginx

方法二:修改Nginx配置文件实现转发

添加配置内容到 nginx.conf

 error_log syslog:server=localhost:514,facility=local7,tag=nginx_error,severity=error;
access_log syslog:server=localhost:514,facility=local7,tag=nginx_access,severity=info;

nginx.conf

# cat /etc/nginx/nginx.conf
#添加 error_log syslog:server=localhost:514,facility=local7,tag=nginx_error,severity=error;
#     access_log syslog:server=localhost:514,facility=local7,tag=nginx_access,severity=info;

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
error_log syslog:server=localhost:514,facility=local7,tag=nginx_error,severity=error;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;
access_log syslog:server=localhost:514,facility=local7,tag=nginx_access,severity=info;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

结果如图

方法三:golang程序监听文件实现转发

1.首先在本地尝试发送数据给rsyslog容器

main.go

package main

import (
    "fmt"
    "log"
    "log/syslog"
)

func main() {
    // 连接到本地的 syslog 服务器,使用 TCP 协议
    sysLog, err := syslog.Dial("tcp", "localhost:514", syslog.LOG_INFO, "myApp")
    if err != nil {
        log.Fatal(err)
    }
    defer sysLog.Close()

    // 发送一条紧急级别的日志消息
    sysLog.Emerg("An emergency message via TCP")

    // 发送一条信息级别的日志消息
    sysLog.Info("This is an informational message via TCP")

    msg := fmt.Sprintf("A formatted message with number %d", 42)
    sysLog.Info(msg)
}

2.读取本地文件到rsyslog容器

package main

import (
    "bufio"
    "log"
    "log/syslog"
    "os"
)

func main() {
    // 连接到本地的 syslog 服务器,使用 TCP 协议
    sysLog, err := syslog.Dial("tcp", "localhost:514", syslog.LOG_INFO, "nginx")
    if err != nil {
        log.Fatal(err)
    }
    defer sysLog.Close()

    // 打开本地日志文件
    logFile, err := os.Open("./access.log")
    if err != nil {
        log.Fatal(err)
    }
    defer logFile.Close()

    // 创建一个新的 bufio 读取器来读取日志文件
    reader := bufio.NewReader(logFile)

    // 逐行读取日志文件并发送到 rsyslog 服务器
    for {
        line, err := reader.ReadString('\n')
        if err != nil {
            // 如果读取到文件末尾或发生错误,则退出循环
            log.Printf("读取到文件末尾或读取日志时出错: %v", err)
            break
        }

        // 发送日志行到 rsyslog 服务器
        if err := sysLog.Info(line); err != nil {
            log.Printf("发送日志时出错: %v", err)
            break
        }
    }
}

3.golang程序监听文件实现转发

main.go

package main

import (
    "bufio"
    "errors"
    "io"
    "log"
    "log/syslog"
    "os"
    "time"
)

func main() {
    // 这里连接到本地的syslog服务器,实际根据配置文件开放的协议端口修改,localhost改成rsyslog服务器地址,syslog.LOG_INFO改成实际对应的日志级别, 修改tag成实际日志来源名称
    sysLog, err := syslog.Dial("tcp", "localhost:514", syslog.LOG_INFO, "nginx_test")
  #转发前"GET /group1/M00 HTTP/1.11estretestgtsttttt1" 400 173 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0"
  #syslog接收后" Oct 11 18:56:19 VM-4-7-ubuntu nginx_test[986243]: 11.42.240.165 - - [14/May/2024:23:13:27 +0800] "GET /group1/M00 HTTP/1.11estretestgtsttttt1" 400 173 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125."0""
    if err != nil {
        log.Fatalf("无法连接到 syslog 服务器: %v", err)
    }
    defer sysLog.Close()

    // 打开本地日志文件 视情况填写成需要的日志地址
    logFile, err := os.Open("./access.log")
    if err != nil {
        log.Fatalf("无法打开日志文件: %v", err)
    }
    defer logFile.Close()

    reader := bufio.NewReader(logFile)

    for {
        // 读取日志文件的一行
        line, err := reader.ReadString('\n')

        // 处理读取错误
        if err != nil {
            if errors.Is(err, io.EOF) {
                log.Println("已到达文件末尾 (EOF)")
            } else {
                log.Printf("读取日志时出错: %v", err)
            }
            time.Sleep(5 * time.Second)
            continue
        }

        // 发送日志行到 rsyslog 服务器
        if err := sendLog(sysLog, line); err != nil {
            log.Printf("发送日志时出错: %v", err)
            sysLog, err = reconnectSyslog()
            if err != nil {
                log.Fatalf("重新连接到 syslog 服务器失败: %v", err)
            }
        }
    }
}

// 发送日志到 syslog
func sendLog(sysLog *syslog.Writer, line string) error {
    return sysLog.Info(line)
}

// 重新连接到 syslog 服务器
func reconnectSyslog() (*syslog.Writer, error) {
    return syslog.Dial("tcp", "localhost:514", syslog.LOG_INFO, "nginx_test")
}
#运行main .go
go run main.go
#进入容器并查看日志文件来验证是否成功接收到日志。
sudo docker exec -it my-rsyslog-container sh
 
#cat /var/log/syslog

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值