diff --git a/cmd/ctr/kill.go b/cmd/ctr/kill.go new file mode 100644 index 0000000..1accd88 --- /dev/null +++ b/cmd/ctr/kill.go @@ -0,0 +1,115 @@ +package main + +import ( + gocontext "context" + "fmt" + "strconv" + "strings" + "syscall" + + "github.com/containerd/containerd/api/services/execution" + "github.com/pkg/errors" + "github.com/urfave/cli" +) + +var signalMap = map[string]syscall.Signal{ + "ABRT": syscall.SIGABRT, + "ALRM": syscall.SIGALRM, + "BUS": syscall.SIGBUS, + "CHLD": syscall.SIGCHLD, + "CLD": syscall.SIGCLD, + "CONT": syscall.SIGCONT, + "FPE": syscall.SIGFPE, + "HUP": syscall.SIGHUP, + "ILL": syscall.SIGILL, + "INT": syscall.SIGINT, + "IO": syscall.SIGIO, + "IOT": syscall.SIGIOT, + "KILL": syscall.SIGKILL, + "PIPE": syscall.SIGPIPE, + "POLL": syscall.SIGPOLL, + "PROF": syscall.SIGPROF, + "PWR": syscall.SIGPWR, + "QUIT": syscall.SIGQUIT, + "SEGV": syscall.SIGSEGV, + "STKFLT": syscall.SIGSTKFLT, + "STOP": syscall.SIGSTOP, + "SYS": syscall.SIGSYS, + "TERM": syscall.SIGTERM, + "TRAP": syscall.SIGTRAP, + "TSTP": syscall.SIGTSTP, + "TTIN": syscall.SIGTTIN, + "TTOU": syscall.SIGTTOU, + "UNUSED": syscall.SIGUNUSED, + "URG": syscall.SIGURG, + "USR1": syscall.SIGUSR1, + "USR2": syscall.SIGUSR2, + "VTALRM": syscall.SIGVTALRM, + "WINCH": syscall.SIGWINCH, + "XCPU": syscall.SIGXCPU, + "XFSZ": syscall.SIGXFSZ, +} + +var killCommand = cli.Command{ + Name: "kill", + Usage: "signal a container", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "id", + Usage: "id of the container", + }, + cli.BoolFlag{ + Name: "all, a", + Usage: "send signal to all processes inside the container", + }, + }, + Action: func(context *cli.Context) error { + id := context.String("id") + if id == "" { + return errors.New("container id must be provided") + } + + sigstr := context.Args().First() + if sigstr == "" { + sigstr = "SIGTERM" + } + + signal, err := parseSignal(sigstr) + if err != nil { + return err + } + + containers, err := getExecutionService(context) + if err != nil { + return err + } + killRequest := &execution.KillRequest{ + ID: id, + Signal: uint32(signal), + All: context.Bool("all"), + } + _, err = containers.Kill(gocontext.Background(), killRequest) + if err != nil { + return err + } + return nil + }, +} + +func parseSignal(rawSignal string) (syscall.Signal, error) { + s, err := strconv.Atoi(rawSignal) + if err == nil { + sig := syscall.Signal(s) + for _, msig := range signalMap { + if sig == msig { + return sig, nil + } + } + return -1, fmt.Errorf("unknown signal %q", rawSignal) + } + signal, ok := signalMap[strings.TrimPrefix(strings.ToUpper(rawSignal), "SIG")] + if !ok { + return -1, fmt.Errorf("unknown signal %q", rawSignal) + } + return signal, nil +} diff --git a/cmd/ctr/main.go b/cmd/ctr/main.go index 8c10a64..89c5912 100644 --- a/cmd/ctr/main.go +++ b/cmd/ctr/main.go @@ -52,6 +52,7 @@ containerd client deleteCommand, listCommand, infoCommand, + killCommand, shimCommand, pprofCommand, }