internal/pkg: exec prefix verbose output
All checks were successful
Test / Create distribution (push) Successful in 47s
Test / Sandbox (push) Successful in 2m52s
Test / ShareFS (push) Successful in 4m50s
Test / Hpkg (push) Successful in 5m10s
Test / Sandbox (race detector) (push) Successful in 5m18s
Test / Hakurei (push) Successful in 5m25s
Test / Hakurei (race detector) (push) Successful in 7m32s
Test / Flake checks (push) Successful in 1m41s
All checks were successful
Test / Create distribution (push) Successful in 47s
Test / Sandbox (push) Successful in 2m52s
Test / ShareFS (push) Successful in 4m50s
Test / Hpkg (push) Successful in 5m10s
Test / Sandbox (race detector) (push) Successful in 5m18s
Test / Hakurei (push) Successful in 5m25s
Test / Hakurei (race detector) (push) Successful in 7m32s
Test / Flake checks (push) Successful in 1m41s
This proxies program output through msg with a name and fd prefix. This also avoids introducing additional information to the container via process stdout/stderr. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -1,11 +1,14 @@
|
|||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -16,6 +19,7 @@ import (
|
|||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
"hakurei.app/container/std"
|
"hakurei.app/container/std"
|
||||||
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AbsWork is the container pathname [CureContext.GetWorkDir] is mounted on.
|
// AbsWork is the container pathname [CureContext.GetWorkDir] is mounted on.
|
||||||
@@ -57,7 +61,8 @@ const (
|
|||||||
// Methods of execArtifact does not modify any struct field or underlying arrays
|
// Methods of execArtifact does not modify any struct field or underlying arrays
|
||||||
// referred to by slices.
|
// referred to by slices.
|
||||||
type execArtifact struct {
|
type execArtifact struct {
|
||||||
// Caller-supplied user-facing reporting name.
|
// Caller-supplied user-facing reporting name, guaranteed to be nonzero
|
||||||
|
// during initialisation.
|
||||||
name string
|
name string
|
||||||
// Caller-supplied inner mount points.
|
// Caller-supplied inner mount points.
|
||||||
paths []ExecPath
|
paths []ExecPath
|
||||||
@@ -219,6 +224,23 @@ const (
|
|||||||
execWaitDelay = time.Nanosecond
|
execWaitDelay = time.Nanosecond
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// scanVerbose prefixes program output for a verbose [message.Msg].
|
||||||
|
func scanVerbose(
|
||||||
|
msg message.Msg,
|
||||||
|
done chan<- struct{},
|
||||||
|
prefix string,
|
||||||
|
r io.Reader,
|
||||||
|
) {
|
||||||
|
defer close(done)
|
||||||
|
s := bufio.NewScanner(r)
|
||||||
|
for s.Scan() {
|
||||||
|
msg.Verbose(prefix, s.Text())
|
||||||
|
}
|
||||||
|
if err := s.Err(); err != nil && !errors.Is(err, os.ErrClosed) {
|
||||||
|
msg.Verbose("*"+prefix, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// cure is like Cure but allows optional host net namespace. This is used for
|
// cure is like Cure but allows optional host net namespace. This is used for
|
||||||
// the [KnownChecksum] variant where networking is allowed.
|
// the [KnownChecksum] variant where networking is allowed.
|
||||||
func (a *execArtifact) cure(f *FContext, hostNet bool) (err error) {
|
func (a *execArtifact) cure(f *FContext, hostNet bool) (err error) {
|
||||||
@@ -250,8 +272,26 @@ func (a *execArtifact) cure(f *FContext, hostNet bool) (err error) {
|
|||||||
z.Hostname = "cure-net"
|
z.Hostname = "cure-net"
|
||||||
}
|
}
|
||||||
z.Uid, z.Gid = (1<<10)-1, (1<<10)-1
|
z.Uid, z.Gid = (1<<10)-1, (1<<10)-1
|
||||||
if f.GetMessage().IsVerbose() {
|
if msg := f.GetMessage(); msg.IsVerbose() {
|
||||||
z.Stdout, z.Stderr = os.Stdout, os.Stderr
|
var stdout, stderr io.ReadCloser
|
||||||
|
if stdout, err = z.StdoutPipe(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if stderr, err = z.StderrPipe(); err != nil {
|
||||||
|
_ = stdout.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err != nil && !errors.As(err, new(*exec.ExitError)) {
|
||||||
|
_ = stdout.Close()
|
||||||
|
_ = stderr.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
stdoutDone, stderrDone := make(chan struct{}), make(chan struct{})
|
||||||
|
go scanVerbose(msg, stdoutDone, "("+a.name+":1)", stdout)
|
||||||
|
go scanVerbose(msg, stderrDone, "("+a.name+":2)", stderr)
|
||||||
|
defer func() { <-stdoutDone; <-stderrDone }()
|
||||||
}
|
}
|
||||||
|
|
||||||
z.Dir, z.Env, z.Path, z.Args = a.dir, a.env, a.path, a.args
|
z.Dir, z.Env, z.Path, z.Args = a.dir, a.env, a.path, a.args
|
||||||
|
|||||||
Reference in New Issue
Block a user