mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
044e298507
The error handling on the runc cli is currenly pretty messy because messages to the user are split between regular stderr format and logrus message format. This changes all the error reporting to the cli to only output on stderr and exit(1) for consumers of the api. By default logrus logs to /dev/null so that it is not seen by the user. If the user wants extra and/or structured loggging/errors from runc they can use the `--log` flag to provide a path to the file where they want this information. This allows a consistent behavior on the cli but extra power and information when debugging with logs. This also includes a change to enable the same logging information inside the container's init by adding an init cli command that can share the existing flags for all other runc commands. Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
101 lines
2.3 KiB
Go
101 lines
2.3 KiB
Go
// +build linux
|
|
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
"github.com/codegangsta/cli"
|
|
"github.com/opencontainers/runc/libcontainer"
|
|
)
|
|
|
|
// event struct for encoding the event data to json.
|
|
type event struct {
|
|
Type string `json:"type"`
|
|
ID string `json:"id"`
|
|
Data interface{} `json:"data,omitempty"`
|
|
}
|
|
|
|
var eventsCommand = cli.Command{
|
|
Name: "events",
|
|
Usage: "display container events such as OOM notifications, cpu, memory, IO and network stats",
|
|
ArgsUsage: `<container-id>
|
|
|
|
Where "<container-id>" is the name for the instance of the container.`,
|
|
Description: `The events command displays information about the container. By default the
|
|
information is displayed once every 5 seconds.`,
|
|
Flags: []cli.Flag{
|
|
cli.DurationFlag{Name: "interval", Value: 5 * time.Second, Usage: "set the stats collection interval"},
|
|
cli.BoolFlag{Name: "stats", Usage: "display the container's stats then exit"},
|
|
},
|
|
Action: func(context *cli.Context) {
|
|
container, err := getContainer(context)
|
|
if err != nil {
|
|
fatal(err)
|
|
}
|
|
var (
|
|
stats = make(chan *libcontainer.Stats, 1)
|
|
events = make(chan *event, 1024)
|
|
group = &sync.WaitGroup{}
|
|
)
|
|
group.Add(1)
|
|
go func() {
|
|
defer group.Done()
|
|
enc := json.NewEncoder(os.Stdout)
|
|
for e := range events {
|
|
if err := enc.Encode(e); err != nil {
|
|
logrus.Error(err)
|
|
}
|
|
}
|
|
}()
|
|
if context.Bool("stats") {
|
|
s, err := container.Stats()
|
|
if err != nil {
|
|
fatal(err)
|
|
}
|
|
events <- &event{Type: "stats", ID: container.ID(), Data: s}
|
|
close(events)
|
|
group.Wait()
|
|
return
|
|
}
|
|
go func() {
|
|
for range time.Tick(context.Duration("interval")) {
|
|
s, err := container.Stats()
|
|
if err != nil {
|
|
logrus.Error(err)
|
|
continue
|
|
}
|
|
stats <- s
|
|
}
|
|
}()
|
|
n, err := container.NotifyOOM()
|
|
if err != nil {
|
|
fatal(err)
|
|
}
|
|
for {
|
|
select {
|
|
case _, ok := <-n:
|
|
if ok {
|
|
// this means an oom event was received, if it is !ok then
|
|
// the channel was closed because the container stopped and
|
|
// the cgroups no longer exist.
|
|
events <- &event{Type: "oom", ID: container.ID()}
|
|
} else {
|
|
n = nil
|
|
}
|
|
case s := <-stats:
|
|
events <- &event{Type: "stats", ID: container.ID(), Data: s}
|
|
}
|
|
if n == nil {
|
|
close(events)
|
|
break
|
|
}
|
|
}
|
|
group.Wait()
|
|
},
|
|
}
|