package containers import ( "errors" "os" "strings" "github.com/containers/podman/v5/cmd/podman/common" "github.com/containers/podman/v5/cmd/podman/registry" "github.com/containers/podman/v5/cmd/podman/validate" "github.com/containers/podman/v5/pkg/domain/entities" "github.com/spf13/cobra" ) var ( attachDescription = "The podman attach command allows you to attach to a running container using the container's ID or name, either to view its ongoing output or to control it interactively." attachCommand = &cobra.Command{ Use: "attach [options] CONTAINER", Short: "Attach to a running container", Long: attachDescription, RunE: attach, Args: validate.IDOrLatestArgs, ValidArgsFunction: common.AutocompleteContainersRunning, Example: `podman attach ctrID podman attach 1234 podman attach --no-stdin foobar`, } containerAttachCommand = &cobra.Command{ Use: attachCommand.Use, Short: attachCommand.Short, Long: attachCommand.Long, RunE: attachCommand.RunE, Args: validate.IDOrLatestArgs, ValidArgsFunction: attachCommand.ValidArgsFunction, Example: `podman container attach ctrID podman container attach 1234 podman container attach --no-stdin foobar`, } ) var ( attachOpts entities.AttachOptions ) func attachFlags(cmd *cobra.Command) { flags := cmd.Flags() detachKeysFlagName := "detach-keys" flags.StringVar(&attachOpts.DetachKeys, detachKeysFlagName, containerConfig.DetachKeys(), "Select the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-`, where `` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`") _ = cmd.RegisterFlagCompletionFunc(detachKeysFlagName, common.AutocompleteDetachKeys) flags.BoolVar(&attachOpts.NoStdin, "no-stdin", false, "Do not attach STDIN. The default is false") flags.BoolVar(&attachOpts.SigProxy, "sig-proxy", true, "Proxy received signals to the process") } func init() { registry.Commands = append(registry.Commands, registry.CliCommand{ Command: attachCommand, }) attachFlags(attachCommand) validate.AddLatestFlag(attachCommand, &attachOpts.Latest) registry.Commands = append(registry.Commands, registry.CliCommand{ Command: containerAttachCommand, Parent: containerCmd, }) attachFlags(containerAttachCommand) validate.AddLatestFlag(containerAttachCommand, &attachOpts.Latest) } func attach(cmd *cobra.Command, args []string) error { if len(args) > 1 || (len(args) == 0 && !attachOpts.Latest) { return errors.New("attach requires the name or id of one running container or the latest flag") } var name string if len(args) > 0 { name = strings.TrimPrefix(args[0], "/") } attachOpts.Stdin = os.Stdin if attachOpts.NoStdin { attachOpts.Stdin = nil } attachOpts.Stdout = os.Stdout attachOpts.Stderr = os.Stderr return registry.ContainerEngine().ContainerAttach(registry.Context(), name, attachOpts) }