3 回答
TA贡献1786条经验 获得超11个赞
这是使用fsnotifylib 监视日志文件的另一种方法。fsnotify监控xxx.log所在的目录,告诉lumberjackRotate()什么时候删除xxx.log。
import (
"fmt"
"log"
"path/filepath"
"time"
"github.com/fsnotify/fsnotify"
"gopkg.in/natefinch/lumberjack.v2"
)
func main() {
logPath := "./xxx.log"
logName := filepath.Base(logPath)
logger := &lumberjack.Logger{
// Log path
Filename: logPath,
// Log size MB
MaxSize: 10,
// Backup count
MaxBackups: 3,
// expire days
// MaxAge: 28,
// gzip compress
Compress: false,
}
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal(err)
}
defer watcher.Close()
go func() {
for event := range watcher.Events {
if event.Op&fsnotify.Remove == fsnotify.Remove &&
event.Name == logName {
log.Println("rotate log", event.Name)
logger.Rotate()
}
}
}()
err = watcher.Add(filepath.Dir(logPath))
if err != nil {
log.Fatal(err)
}
for {
logger.Write([]byte(fmt.Sprintf("current time:%v\n", time.Now())))
time.Sleep(3 * time.Second)
}
}
TA贡献1831条经验 获得超9个赞
问题”
基于所述行为,我假设这发生在为文件实现 POSIX 兼容行为的操作系统上(因此它运行在具有 Unix 遗产的某些内核上 - 例如 *BSD 或 Linux,或者它是 Mac OS 系统)。在这些系统上,从文件系统中删除文件对该文件系统上的文件存储没有任何影响——只要它至少在一个正在运行的进程中打开。
具体来说,要引用POSIX 文档open(2)
:
如果文件的链接计数为0,则当与该文件关联的所有文件描述符都关闭时,该文件占用的空间将被释放,该文件将不再可访问。
打开文件被认为将其链接计数增加 1,从其文件系统中删除文件与将链接计数减 1 相同。您可以在此处
阅读有关链接计数的更多信息。
假设您正在使用的日志记录包保持日志文件处于打开状态,因此您只需从文件系统的目录中删除文件名,但这绝不会影响日志记录过程。
此外,当任何文件名消失时,不会通知打开文件的进程(在类 Unix 系统上,一个文件可能同时有多个名称——请阅读硬链接)。
解决方案
通常,对于类 Unix 操作系统,有一种方法可以明确要求进程重新打开其日志文件。
偶然地,SIGUSR1
为此使用了一个信号,因此您可以设置一个处理程序(通过signal.Notify
)为此类信号设置一个处理程序,然后将您的日志轮换代码设置kill -USR1
为正在运行的进程,以告诉它重新打开日志文件,这将是重新创建。
当然,可以实施更多涉及的方案,因为您可以使用任何形式的IPC将该命令传达给正在运行的进程。
TA贡献1869条经验 获得超4个赞
删除 xxx.log 后,您可以向正在运行的进程发送一个信号,然后下面的代码将处理该信号并告诉伐木工人创建新的日志文件。
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGUSR1)
go func() {
for _ = range sigs {
// call Rotate() method of lumberjack to create new log file
logger.Rotate()
}
}()
用于删除和轮换日志的命令
# delete log file
rm path/to/xxx.log
# this command would not kill your process, just send a signal to it.
kill -USR1 <your process id>
- 3 回答
- 0 关注
- 180 浏览
添加回答
举报