macOS下logrus/lumberjack如何实现日志文件被删除后自动重建
问题原因
lumberjack 库默认仅在当前写入的日志文件大小达到你配置的 MaxSize 阈值时才会执行轮转逻辑、检查文件是否存在并重建。当你手动删除日志文件时,运行中的进程仍然持有已删除文件的文件描述符,后续日志会继续写入这个失效的文件描述符,不会自动触发重建逻辑。
解决方案
你可以通过主动触发 lumberjack 的轮转逻辑来实现文件删除后的自动重建,常见实现方式有两种:
方式1:监听系统信号手动触发(推荐)
给应用注册 SIGHUP 信号监听,当你手动删除日志文件后,给进程发送 SIGHUP 信号就会自动触发重建,不需要重启应用。
代码示例:
package main import ( "os" "os/signal" "path/filepath" "syscall" "github.com/natefinch/lumberjack" "github.com/sirupsen/logrus" ) func main() { logFolder := "./logs" logger := &lumberjack.Logger{ Filename: filepath.Join(logFolder, "xxx.log"), MaxSize: 10, MaxBackups: 3, Compress: false, } logrus.SetOutput(logger) // 注册信号监听 sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGHUP) go func() { for range sigChan { // 调用 Rotate 方法会直接关闭当前文件,重建新的日志文件 _ = logger.Rotate() logrus.Info("日志文件已重建") } }() // 后续你的应用逻辑 }
使用方式:手动删除日志文件后,执行 kill -HUP <你的应用进程ID> 即可触发重建。
方式2:自动检测文件存在性定时重建
如果不需要人工干预,希望程序自动检测,可以开一个后台 goroutine 定期检查日志文件是否存在,不存在就自动触发 Rotate:
import "time" // 加入到你的初始化逻辑中 go func() { logPath := filepath.Join(logFolder, "xxx.log") // 每30秒检查一次,可自行调整间隔 ticker := time.NewTicker(30 * time.Second) defer ticker.Stop() for range ticker.C { if _, err := os.Stat(logPath); os.IsNotExist(err) { _ = logger.Rotate() logrus.Info("检测到日志文件被删除,已自动重建") } } }()
注意事项
- 两种方式都依赖 lumberjack 暴露的
Rotate()方法,该方法会安全关闭当前打开的日志文件,按照配置执行旧文件备份,再创建新的日志文件,不会丢失正在写入的日志。 - 如果你使用的是封装后的 logrus 实例而不是全局 logrus,只需要对绑定的 lumberjack 实例调用 Rotate 方法即可,逻辑完全一致。
内容的提问来源于stack exchange,提问作者Jerry YY Rain
相关产品推荐
相关产品推荐

