2014-08-27 56 views
1

我有很多記錄器寫入我的應用程序中的不同文件。我試圖添加在應用程序運行時截斷該文件的功能。這裏是我有:截斷打開os.File(訪問被拒絕)

type Resource struct { 
    Logger *ResourceLogger 
    // other stuff pertaining to my resource... 
} 

func (r *Resource) SetLogger(logPath string) { 
    path := logPath + r.Name + ".log" 
    f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) 
    if err != nil { 
     log.Fatalf("Unable to open log file '%v'", path) 
    } 
    r.Logger = &ResourceLogger{log.New(f, "", log.Ldate|log.Ltime), f} 
} 

type ResourceLogger struct { 
    *log.Logger 
    LogFile *os.File 
} 

這使我可以登錄到許多文件,輕鬆一個資源。但是,當我嘗試使用Resource.Logger.LogFile.Truncate(0)時,我得到一個拒絕訪問錯誤。

+3

也許一個文件事件觀察在https://github.com/ActiveState/tail/tree/master/watch /blob/master/tail.go#L265-L303可以提供幫助嗎? – VonC 2014-08-27 18:56:03

+0

很好,謝謝!我會盡快研究。 – kwolfe 2014-08-27 19:07:39

回答

1

我認爲你正在使用Windows,因爲Windows有鎖定文件的習慣。我建議,既然你基本上可以控制日誌寫入和截斷,你可以關閉文件一秒鐘,然後截斷它,而沒有打開的文件句柄。

您必須使用例如互斥鎖來阻止任何人在截斷時嘗試記錄任何內容,並且在完成後重新打開日誌文件進行寫入。下面是你一個粗略的例子:在https://github.com/ActiveState/tail使用

package main 

import (
    "log" 
    "os" 
    "sync" 
) 

type Resource struct { 
    Logger *ResourceLogger 
    // other stuff pertaining to my resource... 
    Name string 
} 

func (r *Resource) SetLogger(logPath string) { 
    path := logPath + r.Name + ".log" 
    f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) 
    if err != nil { 
     log.Fatalf("Unable to open log file '%v'", path) 
    } 
    r.Logger = &ResourceLogger{log.New(f, "", log.Ldate|log.Ltime), f, path, sync.Mutex{}} 
} 

func (r *ResourceLogger) Truncate() { 
    if r.logger != nil { 
     r.logmutex.Lock() 
     r.logfile.Close() 
     os.Truncate(r.logfilename, 0) // The file must not be open on Windows! 
     f, err := os.OpenFile(r.logfilename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) 
     if err != nil { 
      log.Fatalf("Unable to open log file '%v'", r.logfilename) 
     } 
     r.logger = log.New(f, "", log.Ldate|log.Ltime) 
     r.logfile = f 
     r.logmutex.Unlock() 
    } 
} 

type ResourceLogger struct { 
    logger  *log.Logger 
    logfile  *os.File 
    logfilename string 
    logmutex sync.Mutex 
} 

func (r *ResourceLogger) Println(s string) { 
    r.logmutex.Lock() 
    r.logger.Println(s) 
    r.logmutex.Unlock() 
} 

func main() { 
    r := Resource{} 
    r.Name = "jeejee" 
    r.SetLogger("") 

    r.Logger.Println("test one") 
    for { 
     r.Logger.Println("more logging") 
     r.Logger.Truncate() 
    } 
}