mirror of
				https://github.com/linuxkit/linuxkit.git
				synced 2025-10-31 05:12:03 +00:00 
			
		
		
		
	Add logging to /var/log for onboot containers
Signed-off-by: Avi Deitcher <avi@deitcher.net>
This commit is contained in:
		| @@ -83,9 +83,9 @@ func main() { | |||||||
| 		command := os.Args[0] | 		command := os.Args[0] | ||||||
| 		switch { | 		switch { | ||||||
| 		case strings.Contains(command, "onboot"): | 		case strings.Contains(command, "onboot"): | ||||||
| 			os.Exit(runcInit(onbootPath)) | 			os.Exit(runcInit(onbootPath, "onboot")) | ||||||
| 		case strings.Contains(command, "onshutdown"): | 		case strings.Contains(command, "onshutdown"): | ||||||
| 			os.Exit(runcInit(shutdownPath)) | 			os.Exit(runcInit(shutdownPath, "shutdown")) | ||||||
| 		case strings.Contains(command, "containerd"): | 		case strings.Contains(command, "containerd"): | ||||||
| 			systemInitCmd(ctx, []string{}) | 			systemInitCmd(ctx, []string{}) | ||||||
| 			os.Exit(0) | 			os.Exit(0) | ||||||
|   | |||||||
| @@ -1,9 +1,11 @@ | |||||||
| package main | package main | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"io" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"os" | 	"os" | ||||||
| 	"os/exec" | 	"os/exec" | ||||||
|  | 	"path" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"strconv" | 	"strconv" | ||||||
|  |  | ||||||
| @@ -13,9 +15,23 @@ import ( | |||||||
|  |  | ||||||
| const ( | const ( | ||||||
| 	runcBinary = "/usr/bin/runc" | 	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 | 	// do nothing if the path does not exist | ||||||
| 	if _, err := os.Stat(rootPath); err != nil && os.IsNotExist(err) { | 	if _, err := os.Stat(rootPath); err != nil && os.IsNotExist(err) { | ||||||
| 		return 0 | 		return 0 | ||||||
| @@ -39,6 +55,13 @@ func runcInit(rootPath string) int { | |||||||
|  |  | ||||||
| 	status := 0 | 	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 { | 	for _, file := range files { | ||||||
| 		name := file.Name() | 		name := file.Name() | ||||||
| 		path := filepath.Join(rootPath, name) | 		path := filepath.Join(rootPath, name) | ||||||
| @@ -52,8 +75,32 @@ func runcInit(rootPath string) int { | |||||||
| 		} | 		} | ||||||
| 		pidfile := filepath.Join(tmpdir, name) | 		pidfile := filepath.Join(tmpdir, name) | ||||||
| 		cmd := exec.Command(runcBinary, "create", "--bundle", path, "--pid-file", pidfile, 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 { | 		if err := cmd.Run(); err != nil { | ||||||
| 			log.Printf("Error creating %s: %v", name, err) | 			log.Printf("Error creating %s: %v", name, err) | ||||||
| 			status = 1 | 			status = 1 | ||||||
| @@ -91,8 +138,9 @@ func runcInit(rootPath string) int { | |||||||
| 		}() | 		}() | ||||||
|  |  | ||||||
| 		cmd = exec.Command(runcBinary, "start", name) | 		cmd = exec.Command(runcBinary, "start", name) | ||||||
| 		cmd.Stdout = os.Stdout | 		cmd.Stdout = stdout | ||||||
| 		cmd.Stderr = os.Stderr | 		cmd.Stderr = stderr | ||||||
|  |  | ||||||
| 		if err := cmd.Run(); err != nil { | 		if err := cmd.Run(); err != nil { | ||||||
| 			log.Printf("Error starting %s: %v", name, err) | 			log.Printf("Error starting %s: %v", name, err) | ||||||
| 			status = 1 | 			status = 1 | ||||||
| @@ -103,9 +151,24 @@ func runcInit(rootPath string) int { | |||||||
|  |  | ||||||
| 		cleanup(path) | 		cleanup(path) | ||||||
| 		_ = os.Remove(pidfile) | 		_ = 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) | 	_ = 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 | 	return status | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user