From df5374fcfa9c46ea52478b7cc3112f125d87d500 Mon Sep 17 00:00:00 2001 From: Fabricio Voznika Date: Thu, 25 Aug 2022 11:37:38 -0700 Subject: [PATCH] Add `runsc usage` to list of commands Also make `runsc debug` write to stdout and log file to make it easier to see the output when running the command manually. PiperOrigin-RevId: 470042053 --- runsc/cli/main.go | 1 + runsc/cmd/debug.go | 41 ++++++++++++++++--------------- runsc/cmd/events.go | 2 +- runsc/cmd/usage.go | 26 ++++++++++---------- runsc/cmd/util/util.go | 15 +++++++++++ runsc/container/container.go | 18 -------------- runsc/container/container_test.go | 6 ++--- runsc/sandbox/sandbox.go | 6 ++--- test/runner/main.go | 2 +- 9 files changed, 58 insertions(+), 59 deletions(-) diff --git a/runsc/cli/main.go b/runsc/cli/main.go index f9d552426..8f48d8ff6 100644 --- a/runsc/cli/main.go +++ b/runsc/cli/main.go @@ -94,6 +94,7 @@ func Main(version string) { subcommands.Register(new(cmd.Debug), debugGroup) subcommands.Register(new(cmd.Statefile), debugGroup) subcommands.Register(new(cmd.Symbolize), debugGroup) + subcommands.Register(new(cmd.Usage), debugGroup) // Internal commands. const internalGroup = "internal use only" diff --git a/runsc/cmd/debug.go b/runsc/cmd/debug.go index dae7f5542..b42b04776 100644 --- a/runsc/cmd/debug.go +++ b/runsc/cmd/debug.go @@ -140,23 +140,23 @@ func (d *Debug) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) if !c.IsSandboxRunning() { return util.Errorf("container sandbox is not running") } - log.Infof("Found sandbox %q, PID: %d", c.Sandbox.ID, c.Sandbox.Getpid()) + util.Infof("Found sandbox %q, PID: %d", c.Sandbox.ID, c.Sandbox.Getpid()) // Perform synchronous actions. if d.signal > 0 { pid := c.Sandbox.Getpid() - log.Infof("Sending signal %d to process: %d", d.signal, pid) + util.Infof("Sending signal %d to process: %d", d.signal, pid) if err := unix.Kill(pid, unix.Signal(d.signal)); err != nil { return util.Errorf("failed to send signal %d to processs %d", d.signal, pid) } } if d.stacks { - log.Infof("Retrieving sandbox stacks") + util.Infof("Retrieving sandbox stacks") stacks, err := c.Sandbox.Stacks() if err != nil { return util.Errorf("retrieving stacks: %v", err) } - log.Infof(" *** Stack dump ***\n%s", stacks) + util.Infof(" *** Stack dump ***\n%s", stacks) } if d.strace != "" || len(d.logLevel) != 0 || len(d.logPackets) != 0 { args := control.LoggingArgs{} @@ -165,16 +165,16 @@ func (d *Debug) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) // strace not set, nothing to do here. case "off": - log.Infof("Disabling strace") + util.Infof("Disabling strace") args.SetStrace = true case "all": - log.Infof("Enabling all straces") + util.Infof("Enabling all straces") args.SetStrace = true args.EnableStrace = true default: - log.Infof("Enabling strace for syscalls: %s", d.strace) + util.Infof("Enabling strace for syscalls: %s", d.strace) args.SetStrace = true args.EnableStrace = true args.StraceAllowlist = strings.Split(d.strace, ",") @@ -192,7 +192,7 @@ func (d *Debug) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) default: return util.Errorf("invalid log level %q", d.logLevel) } - log.Infof("Setting log level %v", args.Level) + util.Infof("Setting log level %v", args.Level) } if len(d.logPackets) != 0 { @@ -203,18 +203,19 @@ func (d *Debug) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) } args.LogPackets = lp if args.LogPackets { - log.Infof("Enabling packet logging") + util.Infof("Enabling packet logging") } else { - log.Infof("Disabling packet logging") + util.Infof("Disabling packet logging") } } if err := c.Sandbox.ChangeLogging(args); err != nil { return util.Errorf(err.Error()) } - log.Infof("Logging options changed") + util.Infof("Logging options changed") } if d.ps { + util.Infof("Retrieving process list") pList, err := c.Processes() if err != nil { util.Fatalf("getting processes for container: %v", err) @@ -223,7 +224,7 @@ func (d *Debug) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) if err != nil { util.Fatalf("generating JSON: %v", err) } - log.Infof(o) + util.Infof("%s", o) } // Open profiling files. @@ -333,13 +334,13 @@ func (d *Debug) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) case <-readyChan: break // Safe to proceed. case <-signals: - log.Infof("caught signal, waiting at most one more second.") + util.Infof("caught signal, waiting at most one more second.") select { case <-signals: - log.Infof("caught second signal, exiting immediately.") + util.Infof("caught second signal, exiting immediately.") os.Exit(1) // Not finished. case <-time.After(time.Second): - log.Infof("timeout, exiting.") + util.Infof("timeout, exiting.") os.Exit(1) // Not finished. case <-readyChan: break // Safe to proceed. @@ -350,27 +351,27 @@ func (d *Debug) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) errorCount := 0 if blockErr != nil { errorCount++ - log.Infof("error collecting block profile: %v", blockErr) + util.Infof("error collecting block profile: %v", blockErr) os.Remove(blockFile.Name()) } if cpuErr != nil { errorCount++ - log.Infof("error collecting cpu profile: %v", cpuErr) + util.Infof("error collecting cpu profile: %v", cpuErr) os.Remove(cpuFile.Name()) } if heapErr != nil { errorCount++ - log.Infof("error collecting heap profile: %v", heapErr) + util.Infof("error collecting heap profile: %v", heapErr) os.Remove(heapFile.Name()) } if mutexErr != nil { errorCount++ - log.Infof("error collecting mutex profile: %v", mutexErr) + util.Infof("error collecting mutex profile: %v", mutexErr) os.Remove(mutexFile.Name()) } if traceErr != nil { errorCount++ - log.Infof("error collecting trace profile: %v", traceErr) + util.Infof("error collecting trace profile: %v", traceErr) os.Remove(traceFile.Name()) } diff --git a/runsc/cmd/events.go b/runsc/cmd/events.go index beb0c1258..b5ac25306 100644 --- a/runsc/cmd/events.go +++ b/runsc/cmd/events.go @@ -72,7 +72,7 @@ func (evs *Events) SetFlags(f *flag.FlagSet) { } // Execute implements subcommands.Command.Execute. -func (evs *Events) Execute(ctx context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus { +func (evs *Events) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus { if f.NArg() != 1 { f.Usage() return subcommands.ExitUsageError diff --git a/runsc/cmd/usage.go b/runsc/cmd/usage.go index 4ccf87d4e..fed6b82cc 100644 --- a/runsc/cmd/usage.go +++ b/runsc/cmd/usage.go @@ -17,8 +17,6 @@ package cmd import ( "context" "encoding/json" - "fmt" - "os" "github.com/google/subcommands" "gvisor.dev/gvisor/runsc/cmd/util" @@ -69,16 +67,8 @@ func (u *Usage) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) util.Fatalf("loading container: %v", err) } - if !u.fd { - m, err := cont.Usage(u.full) - if err != nil { - util.Fatalf("usage failed: %v", err) - } - if err := json.NewEncoder(os.Stdout).Encode(m); err != nil { - util.Fatalf("Encode MemoryUsage failed: %v", err) - } - } else { - m, err := cont.UsageFD() + if u.fd { + m, err := cont.Sandbox.UsageFD() if err != nil { util.Fatalf("usagefd failed: %v", err) } @@ -88,7 +78,17 @@ func (u *Usage) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) util.Fatalf("Fetch memory usage failed: %v", err) } - fmt.Printf("Mapped %v, Unknown %v, Total %v\n", mapped, unknown, total) + util.Infof("Mapped %v, Unknown %v, Total %v\n", mapped, unknown, total) + } else { + m, err := cont.Sandbox.Usage(u.full) + if err != nil { + util.Fatalf("usage failed: %v", err) + } + encoder := json.NewEncoder(&util.Writer{}) + encoder.SetIndent("", " ") + if err := encoder.Encode(m); err != nil { + util.Fatalf("Encode MemoryUsage failed: %v", err) + } } return subcommands.ExitSuccess } diff --git a/runsc/cmd/util/util.go b/runsc/cmd/util/util.go index 7170e35b8..c38d37e59 100644 --- a/runsc/cmd/util/util.go +++ b/runsc/cmd/util/util.go @@ -37,6 +37,21 @@ type jsonError struct { Time time.Time `json:"time"` } +// Writer writes to log and stdout. +type Writer struct{} + +// Write implements io.Writer. +func (i *Writer) Write(data []byte) (n int, err error) { + log.Infof("%s", data) + return os.Stdout.Write(data) +} + +// Infof writes message to log and stdout. +func Infof(format string, args ...interface{}) { + log.Infof(format, args) + fmt.Printf(format+"\n", args) +} + // Errorf logs error to containerd log (--log), to stderr, and debug logs. It // returns subcommands.ExitFailure for convenience with subcommand.Execute() // methods: diff --git a/runsc/container/container.go b/runsc/container/container.go index 8e0ff3b85..85b11080a 100644 --- a/runsc/container/container.go +++ b/runsc/container/container.go @@ -678,24 +678,6 @@ func (c *Container) Cat(files []string, out *os.File) error { return c.Sandbox.Cat(c.ID, files, out) } -// Usage displays memory used by the application. -func (c *Container) Usage(full bool) (control.MemoryUsage, error) { - log.Debugf("Usage in container, cid: %s, full: %v", c.ID, full) - return c.Sandbox.Usage(c.ID, full) -} - -// UsageFD shows application memory usage using two donated FDs. -func (c *Container) UsageFD() (*control.MemoryUsageRecord, error) { - log.Debugf("UsageFD in container, cid: %s", c.ID) - return c.Sandbox.UsageFD(c.ID) -} - -// Reduce requests that the sentry attempt to reduce its memory usage. -func (c *Container) Reduce(wait bool) error { - log.Debugf("Reduce in container, cid: %s", c.ID) - return c.Sandbox.Reduce(c.ID, wait) -} - // Stream dumps all events to out. func (c *Container) Stream(filters []string, out *os.File) error { log.Debugf("Stream in container, cid: %s", c.ID) diff --git a/runsc/container/container_test.go b/runsc/container/container_test.go index 7fdc5e862..f897259f3 100644 --- a/runsc/container/container_test.go +++ b/runsc/container/container_test.go @@ -2590,7 +2590,7 @@ func TestUsage(t *testing.T) { } for _, full := range []bool{false, true} { - m, err := cont.Usage(full) + m, err := cont.Sandbox.Usage(full) if err != nil { t.Fatalf("error usage from container: %v", err) } @@ -2637,7 +2637,7 @@ func TestUsageFD(t *testing.T) { t.Fatalf("starting container: %v", err) } - m, err := cont.UsageFD() + m, err := cont.Sandbox.UsageFD() if err != nil { t.Fatalf("error usageFD from container: %v", err) } @@ -2683,7 +2683,7 @@ func TestReduce(t *testing.T) { t.Fatalf("starting container: %v", err) } - if err := cont.Reduce(false); err != nil { + if err := cont.Sandbox.Reduce(false); err != nil { t.Fatalf("error reduce from container: %v", err) } } diff --git a/runsc/sandbox/sandbox.go b/runsc/sandbox/sandbox.go index 78f87f547..0016a852f 100644 --- a/runsc/sandbox/sandbox.go +++ b/runsc/sandbox/sandbox.go @@ -1140,7 +1140,7 @@ func (s *Sandbox) Cat(cid string, files []string, out *os.File) error { } // Usage sends the collect call for a container in the sandbox. -func (s *Sandbox) Usage(cid string, Full bool) (control.MemoryUsage, error) { +func (s *Sandbox) Usage(Full bool) (control.MemoryUsage, error) { log.Debugf("Usage sandbox %q", s.ID) conn, err := s.sandboxConnect() if err != nil { @@ -1156,7 +1156,7 @@ func (s *Sandbox) Usage(cid string, Full bool) (control.MemoryUsage, error) { } // UsageFD sends the usagefd call for a container in the sandbox. -func (s *Sandbox) UsageFD(cid string) (*control.MemoryUsageRecord, error) { +func (s *Sandbox) UsageFD() (*control.MemoryUsageRecord, error) { log.Debugf("Usage sandbox %q", s.ID) conn, err := s.sandboxConnect() if err != nil { @@ -1179,7 +1179,7 @@ func (s *Sandbox) UsageFD(cid string) (*control.MemoryUsageRecord, error) { } // Reduce sends the reduce call for a container in the sandbox. -func (s *Sandbox) Reduce(cid string, wait bool) error { +func (s *Sandbox) Reduce(wait bool) error { log.Debugf("Reduce sandbox %q", s.ID) conn, err := s.sandboxConnect() if err != nil { diff --git a/test/runner/main.go b/test/runner/main.go index 468f318e5..87c461058 100644 --- a/test/runner/main.go +++ b/test/runner/main.go @@ -287,7 +287,7 @@ func runRunsc(tc gtest.TestCase, spec *specs.Spec) error { log.Warningf("%s: Got signal: %v", name, s) done := make(chan bool, 1) dArgs := append([]string{}, args...) - dArgs = append(dArgs, "-alsologtostderr=true", "debug", "--stacks", id) + dArgs = append(dArgs, "debug", "--stacks", id) go func(dArgs []string) { debug := exec.Command(specutils.ExePath, dArgs...) debug.Stdout = os.Stdout