|
|
@ -5,6 +5,8 @@ import ( |
|
|
|
"io/ioutil" |
|
|
|
"os" |
|
|
|
"os/signal" |
|
|
|
"sync" |
|
|
|
"time" |
|
|
|
) |
|
|
|
|
|
|
|
func TrapSignal(cb func()) { |
|
|
@ -96,3 +98,101 @@ func WriteFileAtomic(filePath string, newBytes []byte) error { |
|
|
|
err = os.Rename(filePath+".new", filePath) |
|
|
|
return err |
|
|
|
} |
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/* AutoFile usage |
|
|
|
|
|
|
|
// Create/Append to ./autofile_test
|
|
|
|
af, err := OpenAutoFile("autofile_test") |
|
|
|
if err != nil { |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
|
|
|
|
// Stream of writes.
|
|
|
|
// During this time, the file may be moved e.g. by logRotate.
|
|
|
|
for i := 0; i < 60; i++ { |
|
|
|
af.Write([]byte(Fmt("LOOP(%v)", i))) |
|
|
|
time.Sleep(time.Second) |
|
|
|
} |
|
|
|
|
|
|
|
// Close the AutoFile
|
|
|
|
err = af.Close() |
|
|
|
if err != nil { |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
*/ |
|
|
|
|
|
|
|
const autoFileOpenDuration = 1000 * time.Millisecond |
|
|
|
|
|
|
|
// Automatically closes and re-opens file for writing.
|
|
|
|
// This is useful for using a log file with the logrotate tool.
|
|
|
|
type AutoFile struct { |
|
|
|
Path string |
|
|
|
ticker *time.Ticker |
|
|
|
mtx sync.Mutex |
|
|
|
file *os.File |
|
|
|
} |
|
|
|
|
|
|
|
func OpenAutoFile(path string) (af *AutoFile, err error) { |
|
|
|
af = &AutoFile{ |
|
|
|
Path: path, |
|
|
|
ticker: time.NewTicker(autoFileOpenDuration), |
|
|
|
} |
|
|
|
if err = af.openFile(); err != nil { |
|
|
|
return |
|
|
|
} |
|
|
|
go af.processTicks() |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
func (af *AutoFile) Close() error { |
|
|
|
af.ticker.Stop() |
|
|
|
af.mtx.Lock() |
|
|
|
err := af.closeFile() |
|
|
|
af.mtx.Unlock() |
|
|
|
return err |
|
|
|
} |
|
|
|
|
|
|
|
func (af *AutoFile) processTicks() { |
|
|
|
for { |
|
|
|
_, ok := <-af.ticker.C |
|
|
|
if !ok { |
|
|
|
return // Done.
|
|
|
|
} |
|
|
|
fmt.Println("closeFile()") |
|
|
|
af.mtx.Lock() |
|
|
|
af.closeFile() |
|
|
|
af.mtx.Unlock() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func (af *AutoFile) closeFile() (err error) { |
|
|
|
file := af.file |
|
|
|
if file == nil { |
|
|
|
return nil |
|
|
|
} |
|
|
|
af.file = nil |
|
|
|
return file.Close() |
|
|
|
} |
|
|
|
|
|
|
|
func (af *AutoFile) Write(b []byte) (n int, err error) { |
|
|
|
af.mtx.Lock() |
|
|
|
defer af.mtx.Unlock() |
|
|
|
if af.file == nil { |
|
|
|
if err = af.openFile(); err != nil { |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
fmt.Println("Write:", string(b)) |
|
|
|
return af.file.Write(b) |
|
|
|
} |
|
|
|
|
|
|
|
func (af *AutoFile) openFile() error { |
|
|
|
file, err := os.OpenFile(af.Path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0600) |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
} |
|
|
|
af.file = file |
|
|
|
return nil |
|
|
|
} |