diff --git a/diagnostic/log_collector_host.go b/diagnostic/log_collector_host.go index cd50c87d..5218e975 100644 --- a/diagnostic/log_collector_host.go +++ b/diagnostic/log_collector_host.go @@ -4,13 +4,16 @@ import ( "context" "fmt" "os" + "os/exec" "path/filepath" "runtime" ) const ( - linuxManagedLogsPath = "/var/log/cloudflared.err" - darwinManagedLogsPath = "/Library/Logs/com.cloudflare.cloudflared.err.log" + linuxManagedLogsPath = "/var/log/cloudflared.err" + darwinManagedLogsPath = "/Library/Logs/com.cloudflare.cloudflared.err.log" + linuxServiceConfigurationPath = "/etc/systemd/system/cloudflared.service" + linuxSystemdPath = "/run/systemd/system" ) type HostLogCollector struct { @@ -23,6 +26,28 @@ func NewHostLogCollector(client HTTPClient) *HostLogCollector { } } +func extractLogsFromJournalCtl(ctx context.Context) (*LogInformation, error) { + tmp := os.TempDir() + + outputHandle, err := os.Create(filepath.Join(tmp, logFilename)) + if err != nil { + return nil, fmt.Errorf("error opening output file: %w", err) + } + + defer outputHandle.Close() + + command := exec.CommandContext( + ctx, + "journalctl", + "--since", + "2 weeks ago", + "-u", + "cloudflared.service", + ) + + return PipeCommandOutputToFile(command, outputHandle) +} + func getServiceLogPath() (string, error) { switch runtime.GOOS { case "darwin": @@ -55,6 +80,13 @@ func (collector *HostLogCollector) Collect(ctx context.Context) (*LogInformation } if logConfiguration.uid == 0 { + _, statSystemdErr := os.Stat(linuxServiceConfigurationPath) + + _, statServiceConfigurationErr := os.Stat(linuxServiceConfigurationPath) + if statSystemdErr == nil && statServiceConfigurationErr == nil && runtime.GOOS == "linux" { + return extractLogsFromJournalCtl(ctx) + } + path, err := getServiceLogPath() if err != nil { return nil, err diff --git a/diagnostic/log_collector_utils.go b/diagnostic/log_collector_utils.go index 889ca30a..728b5298 100644 --- a/diagnostic/log_collector_utils.go +++ b/diagnostic/log_collector_utils.go @@ -12,7 +12,16 @@ func PipeCommandOutputToFile(command *exec.Cmd, outputHandle *os.File) (*LogInfo stdoutReader, err := command.StdoutPipe() if err != nil { return nil, fmt.Errorf( - "error retrieving output from command '%s': %w", + "error retrieving stdout from command '%s': %w", + command.String(), + err, + ) + } + + stderrReader, err := command.StderrPipe() + if err != nil { + return nil, fmt.Errorf( + "error retrieving stderr from command '%s': %w", command.String(), err, ) @@ -29,7 +38,17 @@ func PipeCommandOutputToFile(command *exec.Cmd, outputHandle *os.File) (*LogInfo _, err = io.Copy(outputHandle, stdoutReader) if err != nil { return nil, fmt.Errorf( - "error copying output from %s to file %s: %w", + "error copying stdout from %s to file %s: %w", + command.String(), + outputHandle.Name(), + err, + ) + } + + _, err = io.Copy(outputHandle, stderrReader) + if err != nil { + return nil, fmt.Errorf( + "error copying stderr from %s to file %s: %w", command.String(), outputHandle.Name(), err,