温馨提示×

Linux Golang日志如何远程传输

小樊
57
2025-08-20 11:25:40
栏目: 编程语言

在Linux环境下,使用Golang进行日志远程传输可以通过多种方式实现。以下是一些常见的方法:

1. 使用TCP/UDP协议

你可以将日志发送到远程服务器的TCP或UDP端口。

TCP示例

客户端(发送日志):

package main

import (
	"log"
	"net"
)

func main() {
	conn, err := net.Dial("tcp", "remote-server:port")
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	logger := log.New(conn, "", log.LstdFlags)
	logger.Println("This is a log message")
}

服务器(接收日志):

package main

import (
	"bufio"
	"fmt"
	"log"
	"net"
)

func main() {
	listener, err := net.Listen("tcp", ":port")
	if err != nil {
		log.Fatal(err)
	}
	defer listener.Close()

	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Println(err)
			continue
		}
		go handleConnection(conn)
	}
}

func handleConnection(conn net.Conn) {
	defer conn.Close()
	reader := bufio.NewReader(conn)
	for {
		line, err := reader.ReadString('\n')
		if err != nil {
			break
		}
		fmt.Print(line)
	}
}

UDP示例

客户端(发送日志):

package main

import (
	"log"
	"net"
)

func main() {
	conn, err := net.Dial("udp", "remote-server:port")
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	logger := log.New(conn, "", log.LstdFlags)
	logger.Println("This is a log message")
}

服务器(接收日志):

package main

import (
	"bufio"
	"fmt"
	"log"
	"net"
)

func main() {
	addr, err := net.ResolveUDPAddr("udp", ":port")
	if err != nil {
		log.Fatal(err)
	}

	conn, err := net.ListenUDP("udp", addr)
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	buf := make([]byte, 1024)
	for {
		n, addr, err := conn.ReadFromUDP(buf)
		if err != nil {
			log.Println(err)
			continue
		}
		fmt.Printf("Received %s from %s\n", string(buf[:n]), addr.String())
	}
}

2. 使用HTTP/HTTPS协议

你可以将日志发送到远程服务器的HTTP或HTTPS端点。

客户端(发送日志):

package main

import (
	"bytes"
	"log"
	"net/http"
)

func main() {
	url := "http://remote-server/log"
	logMessage := "This is a log message"

	resp, err := http.Post(url, "application/json", bytes.NewBuffer([]byte(logMessage)))
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		log.Fatalf("Server returned non-OK status: %s", resp.Status)
	}
}

服务器(接收日志):

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

type LogMessage struct {
	Message string `json:"message"`
}

func logHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Only POST method is allowed", http.StatusMethodNotAllowed)
		return
	}

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, "Failed to read request body", http.StatusBadRequest)
		return
	}
	defer r.Body.Close()

	var logMsg LogMessage
	err = json.Unmarshal(body, &logMsg)
	if err != nil {
		http.Error(w, "Failed to parse JSON", http.StatusBadRequest)
		return
	}

	fmt.Printf("Received log: %s\n", logMsg.Message)
	w.WriteHeader(http.StatusOK)
}

func main() {
	http.HandleFunc("/log", logHandler)
	log.Fatal(http.ListenAndServe(":port", nil))
}

3. 使用消息队列

你可以使用消息队列(如Kafka、RabbitMQ)来传输日志。

客户端(发送日志):

package main

import (
	"log"
	"github.com/Shopify/sarama"
)

func main() {
	config := sarama.NewConfig()
	config.Producer.RequiredAcks = sarama.WaitForAll
	config.Producer.Retry.Max = 5
	config.Producer.Return.Successes = true

	producer, err := sarama.NewSyncProducer([]string{"kafka-broker:9092"}, config)
	if err != nil {
		log.Fatal(err)
	}
	defer producer.Close()

	logMessage := &sarama.ProducerMessage{
		Topic: sarama.StringEncoder("log-topic"),
		Value: sarama.ByteEncoder("This is a log message"),
	}

	partition, offset, err := producer.SendMessage(logMessage)
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("Message is stored in topic(%s)/partition(%d)/offset(%d)\n", "log-topic", partition, offset)
}

服务器(接收日志):

package main

import (
	"fmt"
	"log"
	"github.com/Shopify/sarama"
)

func main() {
	config := sarama.NewConfig()
	config.Consumer.Return.Errors = true

	consumer, err := sarama.NewConsumer([]string{"kafka-broker:9092"}, config)
	if err != nil {
		log.Fatal(err)
	}
	defer consumer.Close()

	partitionConsumer, err := consumer.ConsumePartition("log-topic", 0, sarama.OffsetNewest)
	if err != nil {
		log.Fatal(err)
	}
	defer partitionConsumer.Close()

	for msg := range partitionConsumer.Messages() {
		fmt.Printf("Received message: %s\n", string(msg.Value))
	}
}

选择哪种方法取决于你的具体需求,例如日志的实时性、可靠性、安全性等。

0