操作系统: CentOS 6.9_x64

go语言版本: 1.8.3

问题描述

golang的log模块提供的有写日志功能,示例代码如下:

/*
golang log example
E-Mail : Mike_Zhang@live.com
*/
package main import (
"log"
"os"
) func main() {
logFile,err := os.Create("test1.log")
defer logFile.Close()
if err != nil {
log.Fatalln("open file error!")
}
logger := log.New(logFile,"[Debug]",log.Ldate | log.Ltime | log.Lshortfile)
logger.Println("test debug message")
logger.SetPrefix("[Info]")
logger.Println("test info message") }

运行效果:

[root@local t2]# go build logTest1.go
[root@local t2]# ./logTest1
[root@local t2]# cat test1.log
[Debug]// :: logTest1.go:: test debug message
[Info]// :: logTest1.go:: test info message
[root@local t2]#

go语言的log模块没有提供log rotate接口,但实际开发中我们需要该功能:

我们不希望单个日志过大,否则文本编辑器无法打开,查看比较困难;

更不希望占用太大的存储空间,可以指定最多存多少个日志文件。

解决方案

借助带缓冲的channel来实现。

示例代码如下:

/*
golang log rotate example
E-Mail : Mike_Zhang@live.com
*/ package main import (
"fmt"
"log"
"os"
"time"
) const (
BACKUP_COUNT =
MAX_FILE_BYTES = *
) func doRotate(fPrefix string) {
for j := BACKUP_COUNT; j >= ; j-- {
curFileName := fmt.Sprintf("%s_%d.log",fPrefix,j)
k := j-
preFileName := fmt.Sprintf("%s_%d.log",fPrefix,k) if k == {
preFileName = fmt.Sprintf("%s.log", fPrefix)
}
_,err := os.Stat(curFileName)
if err == nil {
os.Remove(curFileName)
fmt.Println("remove : ", curFileName)
}
_,err = os.Stat(preFileName)
if err == nil {
fmt.Println("rename : ", preFileName, " => ", curFileName)
err = os.Rename(preFileName, curFileName)
if err != nil {
fmt.Println(err)
}
}
}
} func NewLogger(fPrefix string) (*log.Logger, *os.File) {
var logger *log.Logger
fileName := fmt.Sprintf("%s.log", fPrefix)
fmt.Println("fileName :", fileName)
logFile, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, ) if err != nil {
fmt.Println("open file error!")
} else {
logger = log.New(logFile, "[Debug]", log.Ldate|log.Ltime|log.Lshortfile)
}
return logger, logFile
} func logWorker(msgQueue <-chan string) {
fPrefix := "msg"
logger, logFile := NewLogger(fPrefix)
for msg := range msgQueue {
logger.Println(msg)
fi, err2 := logFile.Stat()
if err2 == nil {
if fi.Size() > MAX_FILE_BYTES {
logFile.Close()
doRotate(fPrefix)
logger,logFile = NewLogger(fPrefix)
}
}
}
logFile.Close()
} func main() {
msgQueue := make(chan string, )
go logWorker(msgQueue) for j := ; j <= ; j++ {
msgQueue <- fmt.Sprintf("msg_%d", j)
time.Sleep( * time.Second)
}
close(msgQueue)
return
}

运行效果如下:

[root@local t2]# ./logRotateTest1
fileName : msg.log
rename : msg.log => msg_1.log
fileName : msg.log
rename : msg_1.log => msg_2.log
rename : msg.log => msg_1.log
fileName : msg.log
rename : msg_2.log => msg_3.log
rename : msg_1.log => msg_2.log
rename : msg.log => msg_1.log
fileName : msg.log
^C

讨论

这里只是个简单的示例代码,实现了log rotate,更多功能需自行开发。

好,就这些了,希望对你有帮助。

本文github地址:

https://github.com/mike-zhang/mikeBlogEssays/blob/master/2017/20170614_golang之logRotate.rst

欢迎补充

golang之log rotate的更多相关文章

  1. Golang官方log包详解

    Golang官方log包详解 以下全是代码, 详解在注释中, 请从头到尾看 // Copyright 2009 The Go Authors. All rights reserved. // Use ...

  2. linux log rotate

    今天老大提醒我产线kafka自身的log文件积累了好几个月了,我才发现原来kafka的log4j并删除old log. 第一反应是采用linux自带的logrotate功能,在/etc/logrota ...

  3. golang package log

    package main import ( "log" "os" ) var logger *log.Logger func main() { file, er ...

  4. Golang中log与fmt区别

    关于使用log与使用fmt的区别 最初的就是直接打印出来,之后一点点升级,比如加上输出的时间,加上goroutine之间的并发操作(打印信息并不能一定按照你规定好的顺序输出来 每次输出的顺序可能会不同 ...

  5. Golang Learn Log #0

    Print/Printf 区别 Print: 可以打印出字符串, 和变量 fmt.Println(var) //right fmt.Println("string") //righ ...

  6. golang基础学习---log

    package main import ( "log" ) func init() { log.SetPrefix("TRACE: ") log.SetFlag ...

  7. Golang 标准库log的实现

      原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://gotaly.blog.51cto.com/8861157/1406905 前 ...

  8. Golang 标准库提供的Log(一)

      原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://gotaly.blog.51cto.com/8861157/1405754 G ...

  9. 关于Relay Log无法自己主动删除的问题(Neither --relay-log nor --relay-log-index were used)

    今天查看mysql err日志.发现mysql重新启动时总会有例如以下日志出现: [Warning] Neither --relay-log nor --relay-log-index were us ...

随机推荐

  1. JAVA设计模式-设计原则

    6大原则: 单一职责原则 里氏替换原则 依赖倒置原则 接口隔离原则 迪米特法则 开闭原则 一.单一职责原则 定义:应该有且仅有一个原因引起类的变更 带来的好处: 类的复杂性降低,实现什么职责有清晰明确 ...

  2. linux配置nginx

    相关命令: nginx -s reload  :修改配置后重新加载生效 nginx -s reopen  :重新打开日志文件nginx -t -c /path/to/nginx.conf 测试ngin ...

  3. Android之TextView部分颜色变动

    public class StringHandleExampleActivity extends Activity { /** Called when the activity is first cr ...

  4. 应用内截屏的代码,在Activity中测试可用

    截屏功能让我十分头疼,想做个无需root的又找不到资料.这里暂且分享一个无需root的,在应用内截屏的代码,本文转自:http://blog.csdn.net/csh159/article/detai ...

  5. ADB与AVD的常见问题

    一.adb问题常用解决方法 若是模拟器启动正常,但是adb检测不到模拟器,我们给他一套不解释连招,下面教大家几招基础拳法. 1.基础拳法一:循环自动检测 下图那个小按钮,点它,狠狠的点它,然后点运行, ...

  6. 我的Visual Studio 2013常用快捷键

    声明及广告 所有功能针对C#开发配置而写,部分功能可能由插件提供,我会尽可能标注出相应的插件名称.为行文方便,所有快捷键以大写形式表示.太常用的快捷键,如Ctrl + C, Ctrl + Z, Ctr ...

  7. iOS:自定义导航栏,随着tableView滚动显示和隐藏

    自定义导航栏,随着tableView滚动显示和隐藏 一.介绍 自定义导航栏是APP中很常用的一个功能,通过自定义可以灵活的实现动画隐藏和显示效果.虽然处理系统的导航栏也可以实现,但是这个是有弊端的,因 ...

  8. bash 括号(小括号,双小括号,中括号,双中括号,大括号)

    小括号()和大括号{} 主要包括一下几种 ${var} $(cmd) ()和{} $((exp)) ${var:-string},${var:+string},${var:=string},${var ...

  9. Linux awk 命令

    AWK是一种处理文本文件的语言,是一个强大的文本分析工具. 之所以叫AWK是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的Fam ...

  10. VS2008 打开 VS2010解决方案及项目(转)

    第一步,修改解决方案后缀为sln的文件 Microsoft Visual Studio Solution File, Format Version 11.00  # Visual Studio 201 ...