• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

example1/H15-Mar-2018-8456

example2/H15-Mar-2018-9664

.gitignoreH A D15-Mar-2018284 2821

.travis.ymlH A D15-Mar-2018159 87

LICENSEH A D15-Mar-20181.1 KiB2317

MakefileH A D15-Mar-20181 KiB3934

README.mdH A D15-Mar-20182.6 KiB7559

reopen.goH A D15-Mar-20185.4 KiB255183

reopen_test.goH A D15-Mar-20183.5 KiB153105

README.md

1[![Build Status](https://travis-ci.org/client9/reopen.svg)](https://travis-ci.org/client9/reopen) [![Go Report Card](http://goreportcard.com/badge/client9/reopen)](http://goreportcard.com/report/client9/reopen) [![GoDoc](https://godoc.org/github.com/client9/reopen?status.svg)](https://godoc.org/github.com/client9/reopen) [![license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://raw.githubusercontent.com/client9/reopen/master/LICENSE)
2
3Makes a standard os.File a "reopenable writer" and allows SIGHUP signals
4to reopen log files, as needed by
5[logrotated](https://fedorahosted.org/logrotate/).  This is inspired
6by the C/Posix
7[freopen](http://pubs.opengroup.org/onlinepubs/009695399/functions/freopen.html)
8
9The simple version `reopen.NewFileWriter` does unbuffered writing.  A
10call to `.Reopen` closes the existing file handle, and then re-opens
11it using the original filename.
12
13The more advanced version `reopen.NewBufferedFileWriter` buffers input
14and flushes when the internal buffer is full (with care) or if 30 seconds has
15elapsed.
16
17There is also `reopen.Stderr` and `reopen.Stdout` which implements the `reopen.Reopener` interface (and does nothing on a reopen call).
18
19`reopen.Discard` wraps `ioutil.Discard`
20
21Samples are in `example1` and `example2`.  The `run.sh` scripts are a
22dumb test where the file is rotated underneath the server, and nothing
23is lost.  This is not the most robust test but gives you an idea of how it works.
24
25
26Here's some sample code.
27
28```go
29package main
30
31/* Simple logrotate logger
32 */
33import (
34       "fmt"
35       "log"
36       "net/http"
37       "os"
38       "os/signal"
39       "syscall"
40
41       "github.com/client9/reopen"
42)
43
44func main() {
45        // setup logger to write to our new *reopenable* log file
46
47        f, err := reopen.NewFileWriter("/tmp/example.log")
48        if err != nil {
49           log.Fatalf("Unable to set output log: %s", err)
50        }
51        log.SetOutput(f)
52
53        // Handle SIGHUP
54        //
55        // channel is number of signals needed to catch  (more or less)
56        // we only are working with one here, SIGHUP
57        sighup := make(chan os.Signal, 1)
58        signal.Notify(sighup, syscall.SIGHUP)
59        go func() {
60           for {
61               <-sighup
62              fmt.Println("Got a sighup")
63              f.Reopen()
64            }
65         }()
66
67        // dumb http server that just prints and logs the path
68        http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
69            log.Printf("%s", r.URL.Path)
70            fmt.Fprintf(w, "%s\n", r.URL.Path)
71        })
72        log.Fatal(http.ListenAndServe("127.0.0.1:8123", nil))
73}
74```
75