Add print exec stderr to logs for debug level

This commit is contained in:
Alex X
2024-05-27 20:23:55 +03:00
parent 4534b4d8ca
commit 3932dbaa84
+37 -18
View File
@@ -4,7 +4,7 @@ import (
"crypto/md5" "crypto/md5"
"encoding/hex" "encoding/hex"
"errors" "errors"
"io" "fmt"
"net/url" "net/url"
"os" "os"
"os/exec" "os/exec"
@@ -68,8 +68,9 @@ func execHandle(rawURL string) (core.Producer, error) {
args := shell.QuoteSplit(rawURL[5:]) // remove `exec:` args := shell.QuoteSplit(rawURL[5:]) // remove `exec:`
cmd := exec.Command(args[0], args[1:]...) cmd := exec.Command(args[0], args[1:]...)
if log.Debug().Enabled() { cmd.Stderr = &logWriter{
cmd.Stderr = os.Stderr buf: make([]byte, 512),
debug: log.Debug().Enabled(),
} }
if path == "" { if path == "" {
@@ -104,18 +105,10 @@ func handlePipe(_ string, cmd *exec.Cmd, query url.Values) (core.Producer, error
log.Debug().Stringer("launch", time.Since(ts)).Msg("[exec] run pipe") log.Debug().Stringer("launch", time.Since(ts)).Msg("[exec] run pipe")
return prod, err return prod, fmt.Errorf("exec/pipe: %w\n%s", err, cmd.Stderr)
} }
func handleRTSP(url string, cmd *exec.Cmd, path string) (core.Producer, error) { func handleRTSP(url string, cmd *exec.Cmd, path string) (core.Producer, error) {
stderr := limitBuffer{buf: make([]byte, 512)}
if cmd.Stderr != nil {
cmd.Stderr = io.MultiWriter(cmd.Stderr, &stderr)
} else {
cmd.Stderr = &stderr
}
if log.Trace().Enabled() { if log.Trace().Enabled() {
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
} }
@@ -150,10 +143,10 @@ func handleRTSP(url string, cmd *exec.Cmd, path string) (core.Producer, error) {
case <-time.After(time.Second * 60): case <-time.After(time.Second * 60):
_ = cmd.Process.Kill() _ = cmd.Process.Kill()
log.Error().Str("url", url).Msg("[exec] timeout") log.Error().Str("url", url).Msg("[exec] timeout")
return nil, errors.New("timeout") return nil, errors.New("exec: timeout")
case <-done: case <-done:
// limit message size // limit message size
return nil, errors.New("exec: " + stderr.String()) return nil, fmt.Errorf("exec/rtsp\n%s", cmd.Stderr)
case prod := <-waiter: case prod := <-waiter:
log.Debug().Stringer("launch", time.Since(ts)).Msg("[exec] run rtsp") log.Debug().Stringer("launch", time.Since(ts)).Msg("[exec] run rtsp")
return prod, nil return prod, nil
@@ -168,21 +161,47 @@ var (
waitersMu sync.Mutex waitersMu sync.Mutex
) )
type limitBuffer struct { type logWriter struct {
buf []byte buf []byte
debug bool
n int n int
} }
func (l *limitBuffer) String() string { func (l *logWriter) String() string {
if l.n == len(l.buf) { if l.n == len(l.buf) {
return string(l.buf) + "..." return string(l.buf) + "..."
} }
return string(l.buf[:l.n]) return string(l.buf[:l.n])
} }
func (l *limitBuffer) Write(p []byte) (int, error) { func (l *logWriter) Write(p []byte) (n int, err error) {
if l.n < cap(l.buf) { if l.n < cap(l.buf) {
l.n += copy(l.buf[l.n:], p) l.n += copy(l.buf[l.n:], p)
} }
return len(p), nil n = len(p)
if l.debug {
if p = trimSpace(p); p != nil {
log.Debug().Msgf("[exec] %s", p)
}
}
return
}
func trimSpace(b []byte) []byte {
start := 0
stop := len(b)
for ; start < stop; start++ {
if b[start] >= ' ' {
break // trim all ASCII before 0x20
}
}
for ; ; stop-- {
if stop == start {
return nil // skip empty output
}
if b[stop-1] > ' ' {
break // trim all ASCII before 0x21
}
}
return b[start:stop]
} }