From cc57288b64ad238ac2140b3417f72762beeea8de Mon Sep 17 00:00:00 2001 From: Avi Deitcher Date: Thu, 15 Feb 2018 21:59:53 +0200 Subject: [PATCH] Add logging to /var/log for onboot containers Signed-off-by: Avi Deitcher --- pkg/init/cmd/service/main.go | 4 +- pkg/init/cmd/service/runc.go | 73 +++++++++++++++++++++++++++++++++--- 2 files changed, 70 insertions(+), 7 deletions(-) diff --git a/pkg/init/cmd/service/main.go b/pkg/init/cmd/service/main.go index 160266682..d4816980c 100644 --- a/pkg/init/cmd/service/main.go +++ b/pkg/init/cmd/service/main.go @@ -83,9 +83,9 @@ func main() { command := os.Args[0] switch { case strings.Contains(command, "onboot"): - os.Exit(runcInit(onbootPath)) + os.Exit(runcInit(onbootPath, "onboot")) case strings.Contains(command, "onshutdown"): - os.Exit(runcInit(shutdownPath)) + os.Exit(runcInit(shutdownPath, "shutdown")) case strings.Contains(command, "containerd"): systemInitCmd(ctx, []string{}) os.Exit(0) diff --git a/pkg/init/cmd/service/runc.go b/pkg/init/cmd/service/runc.go index 4a0f4fe28..ba242129f 100644 --- a/pkg/init/cmd/service/runc.go +++ b/pkg/init/cmd/service/runc.go @@ -1,9 +1,11 @@ package main import ( + "io" "io/ioutil" "os" "os/exec" + "path" "path/filepath" "strconv" @@ -13,9 +15,23 @@ import ( const ( runcBinary = "/usr/bin/runc" + logDirBase = "/run/log/" + varLogDir = "/var/log" ) -func runcInit(rootPath string) int { +func dumpFile(w io.Writer, filePath string) error { + f, err := os.OpenFile(filePath, os.O_RDONLY, 0644) + if err != nil { + return err + } + defer f.Close() + + _, err = io.Copy(w, f) + + return err +} + +func runcInit(rootPath, serviceType string) int { // do nothing if the path does not exist if _, err := os.Stat(rootPath); err != nil && os.IsNotExist(err) { return 0 @@ -39,6 +55,13 @@ func runcInit(rootPath string) int { status := 0 + logDir := path.Join(logDirBase, serviceType) + varLogLink := path.Join(varLogDir, serviceType) + + if err := os.MkdirAll(logDir, 0755); err != nil { + log.Fatalf("Cannot create log directory %s: %v", logDir, err) + } + for _, file := range files { name := file.Name() path := filepath.Join(rootPath, name) @@ -52,8 +75,32 @@ func runcInit(rootPath string) int { } pidfile := filepath.Join(tmpdir, name) cmd := exec.Command(runcBinary, "create", "--bundle", path, "--pid-file", pidfile, name) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr + + // stream stdout and stderr to respective files + // ideally we want to use io.MultiWriter here, sending one stream to stdout/stderr, another to the files + // however, this hangs if we do, due to a runc bug, see https://github.com/opencontainers/runc/issues/1721#issuecomment-366315563 + // once that is fixed, this can be cleaned up + stdoutFile := filepath.Join(logDir, serviceType+"."+name+".out.log") + stdout, err := os.OpenFile(stdoutFile, os.O_WRONLY|os.O_CREATE, 0644) + if err != nil { + log.Printf("Error opening stdout log file: %v", err) + status = 1 + continue + } + defer stdout.Close() + + stderrFile := filepath.Join(logDir, serviceType+"."+name+".err.log") + stderr, err := os.OpenFile(stderrFile, os.O_WRONLY|os.O_CREATE, 0644) + if err != nil { + log.Printf("Error opening stderr log file: %v", err) + status = 1 + continue + } + defer stderr.Close() + + cmd.Stdout = stdout + cmd.Stderr = stderr + if err := cmd.Run(); err != nil { log.Printf("Error creating %s: %v", name, err) status = 1 @@ -91,8 +138,9 @@ func runcInit(rootPath string) int { }() cmd = exec.Command(runcBinary, "start", name) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr + cmd.Stdout = stdout + cmd.Stderr = stderr + if err := cmd.Run(); err != nil { log.Printf("Error starting %s: %v", name, err) status = 1 @@ -103,9 +151,24 @@ func runcInit(rootPath string) int { cleanup(path) _ = os.Remove(pidfile) + + // dump the log file outputs to os.Stdout/os.Stderr + if err = dumpFile(os.Stdout, stdoutFile); err != nil { + log.Printf("Error writing stdout of onboot service %s to console: %v", name, err) + } + if err = dumpFile(os.Stderr, stderrFile); err != nil { + log.Printf("Error writing stderr of onboot service %s to console: %v", name, err) + } } _ = os.RemoveAll(tmpdir) + // make sure the link exists from /var/log/onboot -> /run/log/onboot + if err := os.MkdirAll(varLogDir, 0755); err != nil { + log.Printf("Error creating secondary log directory %s: %v", varLogDir, err) + } else if err := os.Symlink(logDir, varLogLink); err != nil && !os.IsExist(err) { + log.Printf("Error creating symlink from %s to %s: %v", varLogLink, logDir, err) + } + return status }