mirror of
https://github.com/bettercap/bettercap
synced 2025-08-20 21:43:18 -07:00
new: added log rotation (closes #374)
This commit is contained in:
parent
b6f320d719
commit
fc7d8d22b4
5 changed files with 161 additions and 7 deletions
6
Gopkg.lock
generated
6
Gopkg.lock
generated
|
@ -59,7 +59,7 @@
|
||||||
revision = "f58a169a71a51037728990b2d3597a14f56b525b"
|
revision = "f58a169a71a51037728990b2d3597a14f56b525b"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:bfbb93ae71a839764d94c1ba50f3868ecc576871274cf29db1903bf32efce620"
|
digest = "1:b44604e0c8da17e780203bfd9388d65db31d4ee039347ea92788412e7737a08c"
|
||||||
name = "github.com/evilsocket/islazy"
|
name = "github.com/evilsocket/islazy"
|
||||||
packages = [
|
packages = [
|
||||||
"data",
|
"data",
|
||||||
|
@ -71,8 +71,8 @@
|
||||||
"zip",
|
"zip",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "e86063a516840e32de87d39c214a6937b4d22e04"
|
revision = "be7e564817af1379a350998577006745039f599f"
|
||||||
version = "v1.8.0"
|
version = "v1.9.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
# unused-packages = true
|
# unused-packages = true
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/evilsocket/islazy"
|
name = "github.com/evilsocket/islazy"
|
||||||
version = "1.8.0"
|
version = "1.9.0"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bettercap/bettercap/log"
|
"github.com/bettercap/bettercap/log"
|
||||||
|
@ -14,9 +15,20 @@ import (
|
||||||
"github.com/evilsocket/islazy/tui"
|
"github.com/evilsocket/islazy/tui"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type rotation struct {
|
||||||
|
sync.Mutex
|
||||||
|
Enabled bool
|
||||||
|
Compress bool
|
||||||
|
Format string
|
||||||
|
How string
|
||||||
|
Period int
|
||||||
|
}
|
||||||
|
|
||||||
type EventsStream struct {
|
type EventsStream struct {
|
||||||
session.SessionModule
|
session.SessionModule
|
||||||
|
outputName string
|
||||||
output *os.File
|
output *os.File
|
||||||
|
rotation rotation
|
||||||
ignoreList *IgnoreList
|
ignoreList *IgnoreList
|
||||||
waitFor string
|
waitFor string
|
||||||
waitChan chan *session.Event
|
waitChan chan *session.Event
|
||||||
|
@ -117,6 +129,28 @@ func NewEventsStream(s *session.Session) *EventsStream {
|
||||||
"",
|
"",
|
||||||
"If not empty, events will be written to this file instead of the standard output."))
|
"If not empty, events will be written to this file instead of the standard output."))
|
||||||
|
|
||||||
|
stream.AddParam(session.NewBoolParameter("events.stream.output.rotate",
|
||||||
|
"true",
|
||||||
|
"If true will enable log rotation."))
|
||||||
|
|
||||||
|
stream.AddParam(session.NewBoolParameter("events.stream.output.rotate.compress",
|
||||||
|
"true",
|
||||||
|
"If true will enable log rotation compression."))
|
||||||
|
|
||||||
|
stream.AddParam(session.NewStringParameter("events.stream.output.rotate.how",
|
||||||
|
"size",
|
||||||
|
"(size|time)",
|
||||||
|
"Rotate by 'size' or 'time'."))
|
||||||
|
|
||||||
|
stream.AddParam(session.NewStringParameter("events.stream.output.rotate.format",
|
||||||
|
"2006-01-02 15:04:05",
|
||||||
|
"",
|
||||||
|
"Datetime format to use for log rotation file names."))
|
||||||
|
|
||||||
|
stream.AddParam(session.NewIntParameter("events.stream.output.rotate.when",
|
||||||
|
"10485760",
|
||||||
|
"File size or time duration in seconds for log rotation."))
|
||||||
|
|
||||||
stream.AddParam(session.NewBoolParameter("events.stream.http.request.dump",
|
stream.AddParam(session.NewBoolParameter("events.stream.http.request.dump",
|
||||||
"false",
|
"false",
|
||||||
"If true all HTTP requests will be dumped."))
|
"If true all HTTP requests will be dumped."))
|
||||||
|
@ -146,10 +180,24 @@ func (s *EventsStream) Configure() (err error) {
|
||||||
if err, output = s.StringParam("events.stream.output"); err == nil {
|
if err, output = s.StringParam("events.stream.output"); err == nil {
|
||||||
if output == "" {
|
if output == "" {
|
||||||
s.output = os.Stdout
|
s.output = os.Stdout
|
||||||
} else if output, err = fs.Expand(output); err == nil {
|
} else if s.outputName, err = fs.Expand(output); err == nil {
|
||||||
s.output, err = os.OpenFile(output, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
s.output, err = os.OpenFile(s.outputName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
}
|
}
|
||||||
} else if err, s.dumpHttpReqs = s.BoolParam("events.stream.http.request.dump"); err != nil {
|
}
|
||||||
|
|
||||||
|
if err, s.rotation.Enabled = s.BoolParam("events.stream.output.rotate"); err != nil {
|
||||||
|
return err
|
||||||
|
} else if err, s.rotation.Compress = s.BoolParam("events.stream.output.rotate.compress"); err != nil {
|
||||||
|
return err
|
||||||
|
} else if err, s.rotation.Format = s.StringParam("events.stream.output.rotate.format"); err != nil {
|
||||||
|
return err
|
||||||
|
} else if err, s.rotation.How = s.StringParam("events.stream.output.rotate.how"); err != nil {
|
||||||
|
return err
|
||||||
|
} else if err, s.rotation.Period = s.IntParam("events.stream.output.rotate.when"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err, s.dumpHttpReqs = s.BoolParam("events.stream.http.request.dump"); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if err, s.dumpHttpResp = s.BoolParam("events.stream.http.response.dump"); err != nil {
|
} else if err, s.dumpHttpResp = s.BoolParam("events.stream.http.response.dump"); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/bettercap/bettercap/network"
|
"github.com/bettercap/bettercap/network"
|
||||||
"github.com/bettercap/bettercap/session"
|
"github.com/bettercap/bettercap/session"
|
||||||
|
@ -11,6 +12,7 @@ import (
|
||||||
"github.com/google/go-github/github"
|
"github.com/google/go-github/github"
|
||||||
|
|
||||||
"github.com/evilsocket/islazy/tui"
|
"github.com/evilsocket/islazy/tui"
|
||||||
|
"github.com/evilsocket/islazy/zip"
|
||||||
)
|
)
|
||||||
|
|
||||||
const eventTimeFormat = "15:04:05"
|
const eventTimeFormat = "15:04:05"
|
||||||
|
@ -152,6 +154,53 @@ func (s *EventsStream) viewUpdateEvent(e session.Event) {
|
||||||
*update.HTMLURL)
|
*update.HTMLURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *EventsStream) doRotation() {
|
||||||
|
if s.output == os.Stdout {
|
||||||
|
return
|
||||||
|
} else if !s.rotation.Enabled {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s.rotation.Lock()
|
||||||
|
defer s.rotation.Unlock()
|
||||||
|
|
||||||
|
doRotate := false
|
||||||
|
if info, err := s.output.Stat(); err == nil {
|
||||||
|
if s.rotation.How == "size" {
|
||||||
|
doRotate = info.Size() >= int64(s.rotation.Period)
|
||||||
|
} else if s.rotation.How == "time" {
|
||||||
|
doRotate = info.ModTime().Unix()%int64(s.rotation.Period) == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if doRotate {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
name := fmt.Sprintf("%s-%s", s.outputName, time.Now().Format(s.rotation.Format))
|
||||||
|
|
||||||
|
if err := s.output.Close(); err != nil {
|
||||||
|
fmt.Printf("could not close log for rotation: %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.Rename(s.outputName, name); err != nil {
|
||||||
|
fmt.Printf("could not rename %s to %s: %s\n", s.outputName, name, err)
|
||||||
|
} else if s.rotation.Compress {
|
||||||
|
zipName := fmt.Sprintf("%s.zip", name)
|
||||||
|
if err = zip.Files(zipName, []string{name}); err != nil {
|
||||||
|
fmt.Printf("error creating %s: %s", zipName, err)
|
||||||
|
} else if err = os.Remove(name); err != nil {
|
||||||
|
fmt.Printf("error deleting %s: %s", name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s.output, err = os.OpenFile(s.outputName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("could not open %s: %s", s.outputName, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *EventsStream) View(e session.Event, refresh bool) {
|
func (s *EventsStream) View(e session.Event, refresh bool) {
|
||||||
if e.Tag == "sys.log" {
|
if e.Tag == "sys.log" {
|
||||||
s.viewLogEvent(e)
|
s.viewLogEvent(e)
|
||||||
|
@ -176,4 +225,6 @@ func (s *EventsStream) View(e session.Event, refresh bool) {
|
||||||
if refresh && s.output == os.Stdout {
|
if refresh && s.output == os.Stdout {
|
||||||
s.Session.Refresh()
|
s.Session.Refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.doRotation()
|
||||||
}
|
}
|
||||||
|
|
55
vendor/github.com/evilsocket/islazy/zip/files.go
generated
vendored
Normal file
55
vendor/github.com/evilsocket/islazy/zip/files.go
generated
vendored
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
package zip
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/zip"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Files compresses one or many files into a single zip archive file.
|
||||||
|
// Credits: https://golangcode.com/create-zip-files-in-go/
|
||||||
|
func Files(filename string, files []string) error {
|
||||||
|
arc, err := os.Create(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer arc.Close()
|
||||||
|
|
||||||
|
writer := zip.NewWriter(arc)
|
||||||
|
defer writer.Close()
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
in, err := os.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer in.Close()
|
||||||
|
|
||||||
|
info, err := in.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
header, err := zip.FileInfoHeader(info)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using FileInfoHeader() above only uses the basename of the file. If we want
|
||||||
|
// to preserve the folder structure we can overwrite this with the full path.
|
||||||
|
header.Name = file
|
||||||
|
// Change to deflate to gain better compression
|
||||||
|
// see http://golang.org/pkg/archive/zip/#pkg-constants
|
||||||
|
header.Method = zip.Deflate
|
||||||
|
|
||||||
|
w, err := writer.CreateHeader(header)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err = io.Copy(w, in); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue