在Linux环境下,使用Golang进行日志远程传输可以通过多种方式实现。以下是一些常见的方法:
你可以使用Go的net包来创建一个TCP或UDP服务器,用于接收来自客户端的日志消息。
服务器端:
package main
import (
"bufio"
"fmt"
"log"
"net"
)
func main() {
listener, err := net.Listen("tcp", ":12345")
if err != nil {
log.Fatal(err)
}
defer listener.Close()
fmt.Println("Server is listening on port 12345")
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 {
message, err := reader.ReadString('\n')
if err != nil {
log.Println(err)
break
}
fmt.Print(message)
}
}
客户端:
package main
import (
"bufio"
"fmt"
"log"
"net"
"os"
)
func main() {
conn, err := net.Dial("tcp", "localhost:12345")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
go func() {
reader := bufio.NewReader(os.Stdin)
for {
fmt.Print("Enter log message: ")
message, _ := reader.ReadString('\n')
conn.Write([]byte(message))
}
}()
buf := make([]byte, 1024)
for {
n, err := conn.Read(buf)
if err != nil {
log.Println(err)
break
}
fmt.Print(string(buf[:n]))
}
}
服务器端:
package main
import (
"fmt"
"log"
"net"
)
func main() {
address, err := net.ResolveUDPAddr("udp", ":12345")
if err != nil {
log.Fatal(err)
}
conn, err := net.ListenUDP("udp", address)
if err != nil {
log.Fatal(err)
}
defer conn.Close()
fmt.Println("Server is listening on port 12345")
buffer := make([]byte, 1024)
for {
n, addr, err := conn.ReadFromUDP(buffer)
if err != nil {
log.Println(err)
continue
}
fmt.Printf("Received message from %s: %s\n", addr.String(), string(buffer[:n]))
}
}
客户端:
package main
import (
"bufio"
"fmt"
"log"
"net"
"os"
)
func main() {
address, err := net.ResolveUDPAddr("udp", "localhost:12345")
if err != nil {
log.Fatal(err)
}
conn, err := net.DialUDP("udp", nil, address)
if err != nil {
log.Fatal(err)
}
defer conn.Close()
go func() {
reader := bufio.NewReader(os.Stdin)
for {
fmt.Print("Enter log message: ")
message, _ := reader.ReadString('\n')
_, err := conn.Write([]byte(message))
if err != nil {
log.Println(err)
break
}
}
}()
buf := make([]byte, 1024)
for {
n, _, err := conn.ReadFromUDP(buf)
if err != nil {
log.Println(err)
break
}
fmt.Print(string(buf[:n]))
}
}
你可以使用Go的net/http包来创建一个HTTP或HTTPS服务器,用于接收来自客户端的日志消息。
服务器端:
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
)
func main() {
http.HandleFunc("/log", logHandler)
fmt.Println("Server is listening on port 8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
func logHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
body, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
fmt.Println(string(body))
w.WriteHeader(http.StatusOK)
}
客户端:
package main
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"net/http"
)
func main() {
url := "http://localhost:8080/log"
logMessage := "This is a log message"
resp, err := http.Post(url, "text/plain", bytes.NewBuffer([]byte(logMessage)))
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(body))
}
你可以使用消息队列(如RabbitMQ、Kafka等)来传输日志消息。Go有多个库支持这些消息队列系统。
服务器端:
package main
import (
"fmt"
"log"
"github.com/streadway/amqp"
)
func failOnError(err error, msg string) {
if err != nil {
log.Fatalf("%s: %s", msg, err)
}
}
func main() {
conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
failOnError(err, "Failed to connect to RabbitMQ")
defer conn.Close()
ch, err := conn.Channel()
failOnError(err, "Failed to open a channel")
defer ch.Close()
q, err := ch.QueueDeclare(
"log_queue", // name
false, // durable
false, // delete when unused
false, // exclusive
false, // no-wait
nil, // arguments
)
failOnError(err, "Failed to declare a queue")
err = ch.Publish(
"", // exchange
q.Name, // routing key
false, // mandatory
false, // immediate
amqp.Publishing{
ContentType: "text/plain",
Body: []byte("Log message"),
})
failOnError(err, "Failed to publish a message")
fmt.Println(" [x] Sent 'Log message'")
}
客户端:
package main
import (
"fmt"
"log"
"github.com/streadway/amqp"
)
func failOnError(err error, msg string) {
if err != nil {
log.Fatalf("%s: %s", msg, err)
}
}
func main() {
conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
failOnError(err, "Failed to connect to RabbitMQ")
defer conn.Close()
ch, err := conn.Channel()
failOnError(err, "Failed to open a channel")
defer ch.Close()
q, err := ch.QueueDeclare(
"log_queue", // name
false, // durable
false, // delete when unused
false, // exclusive
false, // no-wait
nil, // arguments
)
failOnError(err, "Failed to declare a queue")
msgs, err := ch.Consume(
q.Name, // queue
"", // consumer
true, // auto-ack
false, // exclusive
false, // no-local
false, // no-wait
nil, // args
)
failOnError(err, "Failed to register a consumer")
forever := make(chan bool)
go func() {
for d := range msgs {
fmt.Printf("Received a message: %s\n", d.Body)
}
}()
fmt.Println(" [*] Waiting for logs. To exit press CTRL+C")
<-forever
}
这些方法可以根据你的具体需求进行选择和扩展。例如,你可以添加身份验证、加密、日志格式化等功能。