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
This commit is contained in:
Fabricio Voznika
2022-08-25 11:40:36 -07:00
committed by gVisor bot
parent dc3a84baa5
commit df5374fcfa
9 changed files with 58 additions and 59 deletions
+1
View File
@@ -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"
+21 -20
View File
@@ -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())
}
+1 -1
View File
@@ -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
+13 -13
View File
@@ -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
}
+15
View File
@@ -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:
-18
View File
@@ -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)
+3 -3
View File
@@ -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)
}
}
+3 -3
View File
@@ -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 {
+1 -1
View File
@@ -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