package util import ( "io" "os" "path" "time" rotatelogs "github.com/lestrrat/go-file-rotatelogs" "github.com/sirupsen/logrus" ) func init() { // ========== 核心配置 ========== logDir := "./log" dirPerm := os.FileMode(0777) // 目录权限:pi可读写执行,同组可读执行 filePerm := os.FileMode(0777) // 文件权限:pi可读写,其他可读 today := time.Now().Format("20060102") todayLogFile := path.Join(logDir, "info."+today+".log") logFileTemplate := path.Join(logDir, "info.%Y%m%d.log") // ========== 1. 强制创建目录 + 修复目录归属/权限 ========== if err := os.MkdirAll(logDir, dirPerm); err != nil { logrus.Fatalf("[日志初始化] 创建日志目录失败: %v", err) } // 关键:强制将目录归属当前运行用户(pi),无论之前归属谁 if err := os.Chown(logDir, os.Getuid(), os.Getgid()); err != nil { logrus.Warnf("[日志初始化] 修正目录归属失败(非致命): %v", err) } // 二次校验目录权限(确保不是只读) if err := os.Chmod(logDir, dirPerm); err != nil { logrus.Warnf("[日志初始化] 修正目录权限失败(非致命): %v", err) } // ========== 2. 强制创建今日日志文件 + 修复文件归属/权限 ========== // 打开文件(创建+追加+写入,确保文件存在且权限正确) f, err := os.OpenFile(todayLogFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, filePerm) if err != nil { logrus.Fatalf("[日志初始化] 创建日志文件失败: %v", err) } f.Close() // 关闭临时句柄 // 强制将文件归属当前用户(核心:解决sudo残留的root归属问题) if err := os.Chown(todayLogFile, os.Getuid(), os.Getgid()); err != nil { logrus.Warnf("[日志初始化] 修正文件归属失败(非致命): %v", err) } // 二次校验文件权限 if err := os.Chmod(todayLogFile, filePerm); err != nil { logrus.Warnf("[日志初始化] 修正文件权限失败(非致命): %v", err) } // ========== 3. 初始化日志切割(适配旧版本rotatelogs) ========== writer, err := rotatelogs.New( logFileTemplate, rotatelogs.WithMaxAge(5*24*time.Hour), rotatelogs.WithRotationTime(24*time.Hour), rotatelogs.WithLinkName(path.Join(logDir, "info.log")), ) if err != nil { logrus.Fatalf("[日志初始化] 创建日志切割器失败: %v", err) } // ========== 4. 日志格式配置 ========== logrus.SetFormatter(&logrus.JSONFormatter{ TimestampFormat: "2006-01-02 15:04:05", // 标准Go时间模板 }) logrus.SetLevel(logrus.DebugLevel) logrus.SetReportCaller(true) // 同时输出到控制台+文件 logrus.SetOutput(io.MultiWriter(os.Stdout, writer)) logrus.Info("[日志初始化] 日志配置完成,权限已强制适配pi用户") }