如何将日志写入文件

我试图用 Go 写入一个日志文件。

我尝试了几种方法,但都失败了。以下是我所尝试的:

func TestLogging(t *testing.T) {
if !FileExists("logfile") {
CreateFile("logfile")
}
f, err := os.Open("logfile")
if err != nil {
t.Fatalf("error: %v", err)
}


// attempt #1
log.SetOutput(io.MultiWriter(os.Stderr, f))
log.Println("hello, logfile")


// attempt #2
log.SetOutput(io.Writer(f))
log.Println("hello, logfile")


// attempt #3
log.SetOutput(f)
log.Println("hello, logfile")
}


func FileExists(name string) bool {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}


func CreateFile(name string) error {
fo, err := os.Create(name)
if err != nil {
return err
}
defer func() {
fo.Close()
}()
return nil
}

创建了日志文件,但没有打印或追加任何内容。为什么?

171201 次浏览

os.Open()在过去肯定有不同的工作方式,但这对我很有效:

f, err := os.OpenFile("testlogfile", os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666)
if err != nil {
log.Fatalf("error opening file: %v", err)
}
defer f.Close()


log.SetOutput(f)
log.Println("This is a test log entry")

根据 Go 文档,os.Open()不能在 log.SetOutput上工作,因为它打开文件“ for reading:”

func Open

func Open(name string) (file *File, err error) Open打开名为 如果成功,返回文件上的方法可以是 用于读取; 关联的文件描述符具有模式 O_RDONLY 有一个错误,它将是类型 *PathError

剪辑

defer f.Close()移动到 if err != nil检查后

我更喜欢12 factor 应用程序日志推荐的简单性和灵活性。要追加到日志文件,可以使用 shell 重定向。Go 中的默认日志记录器写入 stderr (2)。

./app 2>> logfile

参见: http://12factor.net/logs

Go 中的默认日志记录器写入 stderr (2)。 重定向到文件

import (
"syscall"
"os"
)
func main(){
fErr, err = os.OpenFile("Errfile", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
syscall.Dup2(int(fErr.Fd()), 1) /* -- stdout */
syscall.Dup2(int(fErr.Fd()), 2) /* -- stderr */


}

这对我有用

  1. 创建了一个名为 logger.go 的包

    package logger
    
    
    import (
    "flag"
    "os"
    "log"
    "go/build"
    )
    
    
    var (
    Log      *log.Logger
    )
    
    
    
    
    func init() {
    // set location of log file
    var logpath = build.Default.GOPATH + "/src/chat/logger/info.log"
    
    
    flag.Parse()
    var file, err1 = os.Create(logpath)
    
    
    if err1 != nil {
    panic(err1)
    }
    Log = log.New(file, "", log.LstdFlags|log.Lshortfile)
    Log.Println("LogFile : " + logpath)
    }
    
    1. 导入软件包到任何你想记录的地方

      package main
      
      
      import (
      "logger"
      )
      
      
      const (
      VERSION = "0.13"
      )
      
      
      func main() {
      
      
      // time to use our logger, print version, processID and number of running process
      logger.Log.Printf("Server v%s pid=%d started with processes: %d", VERSION, os.Getpid(),runtime.GOMAXPROCS(runtime.NumCPU()))
      
      
      }
      

在全局 var中向上声明,以便所有进程在需要时都可以访问。

package main


import (
"log"
"os"
)
var (
outfile, _ = os.Create("path/to/my.log") // update path for your needs
l      = log.New(outfile, "", 0)
)


func main() {
l.Println("hello, log!!!")
}

我通常把日志打印在屏幕上,然后写到一个文件中。希望这对某些人有帮助。

f, err := os.OpenFile("/tmp/orders.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalf("error opening file: %v", err)
}
defer f.Close()
wrt := io.MultiWriter(os.Stdout, f)
log.SetOutput(wrt)
log.Println(" Orders API Called")

如果您在 linux 机器上运行二进制文件,您可以使用 shell 脚本。

覆盖到文件中

./binaryapp > binaryapp.log

附加到文件中

./binaryapp >> binaryapp.log

将 stderr 覆盖到文件中

./binaryapp &> binaryapp.error.log

将 stderr 附加到文件中

./binaryapp &>> binalyapp.error.log

使用 shell 脚本文件可以使它更加动态。

我将日志写入这些文件,这些文件是每天生成的(每天生成一个日志文件)。这种方法对我很有效:

var (
serverLogger *log.Logger
)


func init() {
// set location of log file
date := time.Now().Format("2006-01-02")
var logpath = os.Getenv(constant.XDirectoryPath) + constant.LogFilePath + date + constant.LogFileExtension
os.MkdirAll(os.Getenv(constant.XDirectoryPath)+constant.LogFilePath, os.ModePerm)
flag.Parse()
var file, err1 = os.OpenFile(logpath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)


if err1 != nil {
panic(err1)
}
mw := io.MultiWriter(os.Stdout, file)
serverLogger = log.New(mw, constant.Empty, log.LstdFlags)
serverLogger.Println("LogFile : " + logpath)
}


// LogServer logs to server's log file
func LogServer(logLevel enum.LogLevel, message string) {
_, file, no, ok := runtime.Caller(1)
logLineData := "logger_server.go"
if ok {
file = shortenFilePath(file)
logLineData = fmt.Sprintf(file + constant.ColonWithSpace + strconv.Itoa(no) + constant.HyphenWithSpace)
}
serverLogger.Println(logLineData + logLevel.String() + constant.HyphenWithSpace + message)
}


// ShortenFilePath Shortens file path to a/b/c/d.go tp d.go
func shortenFilePath(file string) string {
short := file
for i := len(file) - 1; i > 0; i-- {
if file[i] == constant.ForwardSlash {
short = file[i+1:]
break
}
}
file = short
return file
}

“ ShortenFilePath ()”方法,用于从文件的完整路径获取文件名。使用“ LogServer ()”方法创建格式化的日志语句(包含: 文件名、行号、日志级别、错误语句等)。.)

基于 Allison 和 Deepak 的回答,我开始使用 Logrus 并且非常喜欢它:

var log = logrus.New()


func init() {


// log to console and file
f, err := os.OpenFile("crawler.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalf("error opening file: %v", err)
}
wrt := io.MultiWriter(os.Stdout, f)


log.SetOutput(wrt)
}

在主函数中有一个延迟 f Close ()

为了帮助其他人,我创建了一个基本的 log 函数来处理这两种情况下的日志记录,如果您想要输出到 stdout,然后打开调试,它直接做一个开关标志,以便您可以选择您的输出。

func myLog(msg ...interface{}) {
defer func() { r := recover(); if r != nil { fmt.Print("Error detected logging:", r) } }()
if conf.DEBUG {
fmt.Println(msg)
} else {
logfile, err := os.OpenFile(conf.LOGDIR+"/"+conf.AppName+".log", os.O_RDWR | os.O_CREATE | os.O_APPEND,0666)
if !checkErr(err) {
log.SetOutput(logfile)
log.Println(msg)
}
defer logfile.Close()
}
}








也许这会帮助你(如果日志文件存在,使用它,如果它不存在,创建它) :

package main


import (
"flag"
"log"
"os"
)
//Se declara la variable Log. Esta será usada para registrar los eventos.
var (
Log *log.Logger = Loggerx()
)


func Loggerx() *log.Logger {
LOG_FILE_LOCATION := os.Getenv("LOG_FILE_LOCATION")
//En el caso que la variable de entorno exista, el sistema usa la configuración del docker.
if LOG_FILE_LOCATION == "" {
LOG_FILE_LOCATION = "../logs/" + APP_NAME + ".log"
} else {
LOG_FILE_LOCATION = LOG_FILE_LOCATION + APP_NAME + ".log"
}
flag.Parse()
//Si el archivo existe se rehusa, es decir, no elimina el archivo log y crea uno nuevo.
if _, err := os.Stat(LOG_FILE_LOCATION); os.IsNotExist(err) {
file, err1 := os.Create(LOG_FILE_LOCATION)
if err1 != nil {
panic(err1)
}
//si no existe,se crea uno nuevo.
return log.New(file, "", log.Ldate|log.Ltime|log.Lshortfile)
} else {
//si existe se rehusa.
file, err := os.OpenFile(LOG_FILE_LOCATION, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
if err != nil {
panic(err)
}
return log.New(file, "", log.Ldate|log.Ltime|log.Lshortfile)
}
}

更多细节: https://su9.co/9BAE74B