service: log stdout and stderr to separate files

Previously we would pass the path `/var/log/service.log` for both
stdout and stderr to containerd. containerd would construct a dict
with the paths as keys[1] and, due to the duplicate key, would only
open one of the files and start one `io.Copy` instance. Writes to
the other stream would be buffered by the pipe connected to
containerd-shim and would eventually block.

If we modified containerd to open the file twice and start 2
`io.Copy` instances, we would end up with the two streams interleaved
together. It seems cleaner to keep the streams separate; therefore
this patch logs stdout to `/var/log/service.out.log` and stderr to
`/var/log/service.err.log`.

[1]
49437711c3/linux/shim/io.go (L51)

Signed-off-by: David Scott <dave.scott@docker.com>
This commit is contained in:
David Scott 2017-09-14 11:08:59 +01:00
parent 3b097e6056
commit 9c35dbaac2

View File

@ -121,17 +121,21 @@ func start(service, sock, basePath, dumpSpec string) (string, uint32, string, er
}
io := func(id string) (containerd.IO, error) {
logfile := filepath.Join("/var/log", service+".log")
// We just need this to exist.
if err := ioutil.WriteFile(logfile, []byte{}, 0600); err != nil {
// if we cannot write to log, discard output
logfile = "/dev/null"
stdoutFile := filepath.Join("/var/log", service+".out.log")
stderrFile := filepath.Join("/var/log", service+".err.log")
// We just need this to exist. If we cannot write to the directory,
// we'll discard output instead.
if err := ioutil.WriteFile(stdoutFile, []byte{}, 0600); err != nil {
stdoutFile = "/dev/null"
}
if err := ioutil.WriteFile(stderrFile, []byte{}, 0600); err != nil {
stderrFile = "/dev/null"
}
return &cio{
containerd.IOConfig{
Stdin: "/dev/null",
Stdout: logfile,
Stderr: logfile,
Stdout: stdoutFile,
Stderr: stderrFile,
Terminal: false,
},
}, nil