constellation/bootstrapper/internal/journald/journald.go
Malte Poll bf06a014a4 bootstrapper: ignore "journald" not in $PATH in constructor
In unit tests, NewCollector may be called on systems that do not have
"journalctl" in $PATH.
We can defer checking if the command can work by not checking cmd.Err in
the constructor.
2023-11-10 18:15:59 +01:00

63 lines
1.3 KiB
Go

/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
/*
Package journald provides functions to read and collect journald logs.
*/
package journald
import (
"context"
"io"
"os/exec"
)
type command interface {
Start() error
Wait() error
}
// Collector collects logs from journald.
type Collector struct {
cmd command
stdoutPipe io.ReadCloser
stderrPipe io.ReadCloser
}
// NewCollector creates a new Collector for journald logs.
func NewCollector(ctx context.Context) (*Collector, error) {
cmd := exec.CommandContext(ctx, "journalctl")
stdoutPipe, err := cmd.StdoutPipe()
if err != nil {
return nil, err
}
stderrPipe, err := cmd.StderrPipe()
if err != nil {
return nil, err
}
collector := Collector{cmd, stdoutPipe, stderrPipe}
return &collector, nil
}
// Start returns a pipe to read the systemd logs. This should be read with a bufio Reader.
func (c *Collector) Start() (io.ReadCloser, error) {
if err := c.cmd.Start(); err != nil {
return nil, err
}
return c.stdoutPipe, nil
}
// Error returns output to stderr as bytes as well
// as the exit code in form of an error.
func (c *Collector) Error() ([]byte, error) {
stderr, err := io.ReadAll(c.stderrPipe)
if err != nil {
return nil, err
}
exitCode := c.cmd.Wait()
return stderr, exitCode
}