package main import ( "context" "errors" "fmt" "strconv" "strings" "github.com/opencontainers/runc/libcontainer" "github.com/urfave/cli/v3" "golang.org/x/sys/unix" ) var killCommand = &cli.Command{ Name: "kill", Usage: "kill sends the specified signal (default: SIGTERM) to the container's init process", ArgsUsage: ` [signal] Where "" is the name for the instance of the container and "[signal]" is the signal to be sent to the init process. EXAMPLE: For example, if the container id is "ubuntu01" the following will send a "KILL" signal to the init process of the "ubuntu01" container: # runc kill ubuntu01 KILL`, // Stop parsing flags after the first positional argument (container ID). StopOnNthArg: mkPtr(1), // Disable comma as separator for slice flags. DisableSliceFlagSeparator: true, Flags: []cli.Flag{ &cli.BoolFlag{ Name: "all", Aliases: []string{"a"}, Usage: "(obsoleted, do not use)", Hidden: true, }, }, Action: func(_ context.Context, cmd *cli.Command) error { if err := checkArgs(cmd, 1, minArgs); err != nil { return err } if err := checkArgs(cmd, 2, maxArgs); err != nil { return err } container, err := getContainer(cmd) if err != nil { return err } sigstr := cmd.Args().Get(1) if sigstr == "" { sigstr = "SIGTERM" } signal, err := parseSignal(sigstr) if err != nil { return err } err = container.Signal(signal) if errors.Is(err, libcontainer.ErrNotRunning) && cmd.Bool("all") { err = nil } return err }, } func parseSignal(rawSignal string) (unix.Signal, error) { s, err := strconv.Atoi(rawSignal) if err == nil { return unix.Signal(s), nil } sig := strings.ToUpper(rawSignal) if !strings.HasPrefix(sig, "SIG") { sig = "SIG" + sig } signal := unix.SignalNum(sig) if signal == 0 { return -1, fmt.Errorf("unknown signal %q", rawSignal) } return signal, nil }