mirror of
https://github.com/zrepl/zrepl.git
synced 2025-01-03 04:48:55 +01:00
zfs: send: improve error reporting by capturing stderr
This commit is contained in:
parent
e675b35cda
commit
99ab16d7be
@ -27,6 +27,14 @@ type CircularLog struct {
|
|||||||
mtx sync.Mutex
|
mtx sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MustNewCircularLog(max int) *CircularLog {
|
||||||
|
log, err := NewCircularLog(max)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return log
|
||||||
|
}
|
||||||
|
|
||||||
func NewCircularLog(max int) (*CircularLog, error) {
|
func NewCircularLog(max int) (*CircularLog, error) {
|
||||||
if max <= 0 {
|
if max <= 0 {
|
||||||
return nil, fmt.Errorf("max must be positive")
|
return nil, fmt.Errorf("max must be positive")
|
||||||
|
17
zfs/zfs.go
17
zfs/zfs.go
@ -17,10 +17,10 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/zrepl/zrepl/util/circlog"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/util/envconst"
|
"github.com/zrepl/zrepl/util/envconst"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -418,6 +418,7 @@ type sendStream struct {
|
|||||||
|
|
||||||
closeMtx sync.Mutex
|
closeMtx sync.Mutex
|
||||||
stdoutReader *os.File
|
stdoutReader *os.File
|
||||||
|
stderrBuf *circlog.CircularLog
|
||||||
opErr error
|
opErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,7 +496,7 @@ func (s *sendStream) killAndWait(precedingReadErr error) error {
|
|||||||
// we managed to tear things down, no let's give the user some pretty *ZFSError
|
// we managed to tear things down, no let's give the user some pretty *ZFSError
|
||||||
if exitErr != nil {
|
if exitErr != nil {
|
||||||
s.opErr = &ZFSError{
|
s.opErr = &ZFSError{
|
||||||
Stderr: exitErr.Stderr,
|
Stderr: []byte(s.stderrBuf.String()),
|
||||||
WaitErr: exitErr,
|
WaitErr: exitErr,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -512,6 +513,8 @@ func (s *sendStream) killAndWait(precedingReadErr error) error {
|
|||||||
return s.opErr
|
return s.opErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var zfsSendStderrCaptureMaxSize = envconst.Int("ZREPL_ZFS_SEND_STDERR_MAX_CAPTURE_SIZE", 1<<15)
|
||||||
|
|
||||||
// if token != "", then send -t token is used
|
// if token != "", then send -t token is used
|
||||||
// otherwise send [-i from] to is used
|
// otherwise send [-i from] to is used
|
||||||
// (if from is "" a full ZFS send is done)
|
// (if from is "" a full ZFS send is done)
|
||||||
@ -538,11 +541,14 @@ func ZFSSend(ctx context.Context, fs string, from, to string, token string) (str
|
|||||||
|
|
||||||
cmd.Stdout = stdoutWriter
|
cmd.Stdout = stdoutWriter
|
||||||
|
|
||||||
|
stderrBuf := circlog.MustNewCircularLog(zfsSendStderrCaptureMaxSize)
|
||||||
|
cmd.Stderr = stderrBuf
|
||||||
|
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
cancel()
|
cancel()
|
||||||
stdoutWriter.Close()
|
stdoutWriter.Close()
|
||||||
stdoutReader.Close()
|
stdoutReader.Close()
|
||||||
return nil, err
|
return nil, errors.Wrap(err, "cannot start zfs send command")
|
||||||
}
|
}
|
||||||
stdoutWriter.Close()
|
stdoutWriter.Close()
|
||||||
|
|
||||||
@ -550,9 +556,10 @@ func ZFSSend(ctx context.Context, fs string, from, to string, token string) (str
|
|||||||
cmd: cmd,
|
cmd: cmd,
|
||||||
kill: cancel,
|
kill: cancel,
|
||||||
stdoutReader: stdoutReader,
|
stdoutReader: stdoutReader,
|
||||||
|
stderrBuf: stderrBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
return newSendStreamCopier(stream), err
|
return newSendStreamCopier(stream), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type DrySendType string
|
type DrySendType string
|
||||||
|
Loading…
Reference in New Issue
Block a user