mirror of
https://github.com/containers/podman.git
synced 2025-10-19 20:23:08 +08:00
Merge pull request #3324 from marcov/detach-keys-configurable
libpod: specify a detach keys sequence in libpod.conf
This commit is contained in:
@ -31,7 +31,7 @@ func init() {
|
|||||||
attachCommand.SetHelpTemplate(HelpTemplate())
|
attachCommand.SetHelpTemplate(HelpTemplate())
|
||||||
attachCommand.SetUsageTemplate(UsageTemplate())
|
attachCommand.SetUsageTemplate(UsageTemplate())
|
||||||
flags := attachCommand.Flags()
|
flags := attachCommand.Flags()
|
||||||
flags.StringVar(&attachCommand.DetachKeys, "detach-keys", "", "Override the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _")
|
flags.StringVar(&attachCommand.DetachKeys, "detach-keys", "", "Override the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`")
|
||||||
flags.BoolVar(&attachCommand.NoStdin, "no-stdin", false, "Do not attach STDIN. The default is false")
|
flags.BoolVar(&attachCommand.NoStdin, "no-stdin", false, "Do not attach STDIN. The default is false")
|
||||||
flags.BoolVar(&attachCommand.SigProxy, "sig-proxy", true, "Proxy received signals to the process")
|
flags.BoolVar(&attachCommand.SigProxy, "sig-proxy", true, "Proxy received signals to the process")
|
||||||
flags.BoolVarP(&attachCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
flags.BoolVarP(&attachCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||||
|
@ -181,7 +181,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
|
|||||||
)
|
)
|
||||||
createFlags.String(
|
createFlags.String(
|
||||||
"detach-keys", "",
|
"detach-keys", "",
|
||||||
"Override the key sequence for detaching a container. Format is a single character `[a-Z]` or `ctrl-<value>` where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`",
|
"Override the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`",
|
||||||
)
|
)
|
||||||
createFlags.StringSlice(
|
createFlags.StringSlice(
|
||||||
"device", []string{},
|
"device", []string{},
|
||||||
|
@ -35,7 +35,7 @@ func init() {
|
|||||||
startCommand.SetUsageTemplate(UsageTemplate())
|
startCommand.SetUsageTemplate(UsageTemplate())
|
||||||
flags := startCommand.Flags()
|
flags := startCommand.Flags()
|
||||||
flags.BoolVarP(&startCommand.Attach, "attach", "a", false, "Attach container's STDOUT and STDERR")
|
flags.BoolVarP(&startCommand.Attach, "attach", "a", false, "Attach container's STDOUT and STDERR")
|
||||||
flags.StringVar(&startCommand.DetachKeys, "detach-keys", "", "Override the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _")
|
flags.StringVar(&startCommand.DetachKeys, "detach-keys", "", "Override the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`")
|
||||||
flags.BoolVarP(&startCommand.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached")
|
flags.BoolVarP(&startCommand.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached")
|
||||||
flags.BoolVarP(&startCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
flags.BoolVarP(&startCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||||
flags.BoolVar(&startCommand.SigProxy, "sig-proxy", false, "Proxy received signals to the process (default true if attaching, false otherwise)")
|
flags.BoolVar(&startCommand.SigProxy, "sig-proxy", false, "Proxy received signals to the process (default true if attaching, false otherwise)")
|
||||||
|
@ -98,6 +98,9 @@ libpod to manage containers.
|
|||||||
**events_logger**=""
|
**events_logger**=""
|
||||||
Default method to use when logging events. Valid values are "journald" and "file".
|
Default method to use when logging events. Valid values are "journald" and "file".
|
||||||
|
|
||||||
|
**detach_keys**=""
|
||||||
|
Keys sequence used for detaching a container
|
||||||
|
|
||||||
## FILES
|
## FILES
|
||||||
`/usr/share/containers/libpod.conf`, default libpod configuration path
|
`/usr/share/containers/libpod.conf`, default libpod configuration path
|
||||||
|
|
||||||
|
@ -11,12 +11,16 @@ The attach command allows you to attach to a running container using the contain
|
|||||||
or name, either to view its ongoing output or to control it interactively.
|
or name, either to view its ongoing output or to control it interactively.
|
||||||
|
|
||||||
You can detach from the container (and leave it running) using a configurable key sequence. The default
|
You can detach from the container (and leave it running) using a configurable key sequence. The default
|
||||||
sequence is `ctrl-p,ctrl-q`. You configure the key sequence using the --detach-keys option
|
sequence is `ctrl-p,ctrl-q`.
|
||||||
|
Configure the keys sequence using the **--detach-keys** option, or specifying
|
||||||
|
it in the **libpod.conf** file: see **libpod.conf(5)** for more information.
|
||||||
|
|
||||||
## OPTIONS
|
## OPTIONS
|
||||||
**--detach-keys**=*char*
|
**--detach-keys**=*sequence*
|
||||||
|
|
||||||
Override the key sequence for detaching a container. Format is a single character `[a-Z]` or `ctrl-<value>` where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`.
|
Override the key sequence for detaching a container. Format is a single character `[a-Z]` or
|
||||||
|
a comma separated sequence of `ctrl-<value>`, where `<value>` is one of:
|
||||||
|
`a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`.
|
||||||
|
|
||||||
**--latest**, **-l**
|
**--latest**, **-l**
|
||||||
|
|
||||||
|
@ -175,12 +175,14 @@ detached container with **podman attach**.
|
|||||||
|
|
||||||
When attached in the tty mode, you can detach from the container (and leave it
|
When attached in the tty mode, you can detach from the container (and leave it
|
||||||
running) using a configurable key sequence. The default sequence is `ctrl-p,ctrl-q`.
|
running) using a configurable key sequence. The default sequence is `ctrl-p,ctrl-q`.
|
||||||
You configure the key sequence using the **--detach-keys** option or a configuration file.
|
Configure the keys sequence using the **--detach-keys** option, or specifying
|
||||||
See **config-json(5)** for documentation on using a configuration file.
|
it in the **libpod.conf** file: see **libpod.conf(5)** for more information.
|
||||||
|
|
||||||
**--detach-keys**=*char*
|
**--detach-keys**=*sequence*
|
||||||
|
|
||||||
Override the key sequence for detaching a container. Format is a single character `[a-Z]` or `ctrl-<value>` where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`.
|
Override the key sequence for detaching a container. Format is a single character `[a-Z]` or
|
||||||
|
a comma separated sequence of `ctrl-<value>`, where `<value>` is one of:
|
||||||
|
`a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`.
|
||||||
|
|
||||||
**--device**=*device*
|
**--device**=*device*
|
||||||
|
|
||||||
|
@ -181,12 +181,14 @@ detached container with **podman attach**.
|
|||||||
|
|
||||||
When attached in the tty mode, you can detach from the container (and leave it
|
When attached in the tty mode, you can detach from the container (and leave it
|
||||||
running) using a configurable key sequence. The default sequence is `ctrl-p,ctrl-q`.
|
running) using a configurable key sequence. The default sequence is `ctrl-p,ctrl-q`.
|
||||||
You configure the key sequence using the **--detach-keys** option or a configuration file.
|
Configure the keys sequence using the **--detach-keys** option, or specifying
|
||||||
See **config-json(5)** for documentation on using a configuration file.
|
it in the **libpod.conf** file: see **libpod.conf(5)** for more information.
|
||||||
|
|
||||||
**--detach-keys**=*char*
|
**--detach-keys**=*sequence*
|
||||||
|
|
||||||
Override the key sequence for detaching a container. Format is a single character `[a-Z]` or `ctrl-<value>` where `<value>` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`.
|
Override the key sequence for detaching a container. Format is a single character `[a-Z]` or
|
||||||
|
a comma separated sequence of `ctrl-<value>`, where `<value>` is one of:
|
||||||
|
`a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`.
|
||||||
|
|
||||||
**--device**=*device*
|
**--device**=*device*
|
||||||
|
|
||||||
|
@ -19,9 +19,11 @@ attach to the container.
|
|||||||
Attach container's STDOUT and STDERR. The default is false. This option cannot be used when
|
Attach container's STDOUT and STDERR. The default is false. This option cannot be used when
|
||||||
starting multiple containers.
|
starting multiple containers.
|
||||||
|
|
||||||
**--detach-keys**=*char*
|
**--detach-keys**=*sequence*
|
||||||
|
|
||||||
Override the key sequence for detaching a container. Format is a single character `[a-Z]` or `ctrl-<value>` where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`.
|
Override the key sequence for detaching a container. Format is a single character `[a-Z]` or
|
||||||
|
a comma separated sequence of `ctrl-<value>`, where `<value>` is one of:
|
||||||
|
`a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`.
|
||||||
|
|
||||||
**--interactive**, **-i**
|
**--interactive**, **-i**
|
||||||
|
|
||||||
|
@ -102,6 +102,13 @@ num_locks = 2048
|
|||||||
# are `journald` or `file`.
|
# are `journald` or `file`.
|
||||||
# events_logger = "journald"
|
# events_logger = "journald"
|
||||||
|
|
||||||
|
# Specify the keys sequence used to detach a container.
|
||||||
|
# Format is a single character [a-Z] or a comma separated sequence of
|
||||||
|
# `ctrl-<value>`, where `<value>` is one of:
|
||||||
|
# `a-z`, `@`, `^`, `[`, `\`, `]`, `^` or `_`
|
||||||
|
#
|
||||||
|
# detach_keys = "ctrl-p,ctrl-q"
|
||||||
|
|
||||||
# Default OCI runtime
|
# Default OCI runtime
|
||||||
runtime = "runc"
|
runtime = "runc"
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containers/libpod/libpod/define"
|
"github.com/containers/libpod/libpod/define"
|
||||||
@ -120,20 +119,24 @@ func (c *Container) StartAndAttach(ctx context.Context, streams *AttachStreams,
|
|||||||
attachChan := make(chan error)
|
attachChan := make(chan error)
|
||||||
|
|
||||||
// We need to ensure that we don't return until start() fired in attach.
|
// We need to ensure that we don't return until start() fired in attach.
|
||||||
// Use a WaitGroup to sync this.
|
// Use a channel to sync
|
||||||
wg := new(sync.WaitGroup)
|
startedChan := make(chan bool)
|
||||||
wg.Add(1)
|
|
||||||
|
|
||||||
// Attach to the container before starting it
|
// Attach to the container before starting it
|
||||||
go func() {
|
go func() {
|
||||||
if err := c.attach(streams, keys, resize, true, wg); err != nil {
|
if err := c.attach(streams, keys, resize, true, startedChan); err != nil {
|
||||||
attachChan <- err
|
attachChan <- err
|
||||||
}
|
}
|
||||||
close(attachChan)
|
close(attachChan)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
wg.Wait()
|
select {
|
||||||
|
case err := <-attachChan:
|
||||||
|
return nil, err
|
||||||
|
case <-startedChan:
|
||||||
c.newContainerEvent(events.Attach)
|
c.newContainerEvent(events.Attach)
|
||||||
|
}
|
||||||
|
|
||||||
return attachChan, nil
|
return attachChan, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/containers/libpod/libpod/define"
|
"github.com/containers/libpod/libpod/define"
|
||||||
"github.com/containers/libpod/pkg/kubeutils"
|
"github.com/containers/libpod/pkg/kubeutils"
|
||||||
@ -33,32 +32,35 @@ const (
|
|||||||
|
|
||||||
// Attach to the given container
|
// Attach to the given container
|
||||||
// Does not check if state is appropriate
|
// Does not check if state is appropriate
|
||||||
func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, wg *sync.WaitGroup) error {
|
func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, started chan bool) error {
|
||||||
if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput {
|
if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput {
|
||||||
return errors.Wrapf(define.ErrInvalidArg, "must provide at least one stream to attach to")
|
return errors.Wrapf(define.ErrInvalidArg, "must provide at least one stream to attach to")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the validity of the provided keys first
|
|
||||||
var err error
|
|
||||||
detachKeys := []byte{}
|
|
||||||
if len(keys) > 0 {
|
|
||||||
detachKeys, err = term.ToBytes(keys)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "invalid detach keys")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logrus.Debugf("Attaching to container %s", c.ID())
|
logrus.Debugf("Attaching to container %s", c.ID())
|
||||||
|
|
||||||
return c.attachContainerSocket(resize, detachKeys, streams, startContainer, wg)
|
return c.attachContainerSocket(resize, keys, streams, startContainer, started)
|
||||||
}
|
}
|
||||||
|
|
||||||
// attachContainerSocket connects to the container's attach socket and deals with the IO.
|
// attachContainerSocket connects to the container's attach socket and deals with the IO.
|
||||||
// wg is only required if startContainer is true
|
// started is only required if startContainer is true
|
||||||
// TODO add a channel to allow interrupting
|
// TODO add a channel to allow interrupting
|
||||||
func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSize, detachKeys []byte, streams *AttachStreams, startContainer bool, wg *sync.WaitGroup) error {
|
func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSize, keys string, streams *AttachStreams, startContainer bool, started chan bool) error {
|
||||||
if startContainer && wg == nil {
|
if startContainer && started == nil {
|
||||||
return errors.Wrapf(define.ErrInternal, "wait group not passed when startContainer set")
|
return errors.Wrapf(define.ErrInternal, "started chan not passed when startContainer set")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use default detach keys when keys aren't passed or specified in libpod.conf
|
||||||
|
if len(keys) == 0 {
|
||||||
|
keys = DefaultDetachKeys
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the validity of the provided keys
|
||||||
|
detachKeys := []byte{}
|
||||||
|
var err error
|
||||||
|
detachKeys, err = term.ToBytes(keys)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "invalid detach keys")
|
||||||
}
|
}
|
||||||
|
|
||||||
kubeutils.HandleResizing(resize, func(size remotecommand.TerminalSize) {
|
kubeutils.HandleResizing(resize, func(size remotecommand.TerminalSize) {
|
||||||
@ -97,7 +99,7 @@ func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSi
|
|||||||
if err := c.start(); err != nil {
|
if err := c.start(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
wg.Done()
|
started <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
receiveStdoutError := make(chan error)
|
receiveStdoutError := make(chan error)
|
||||||
|
@ -3,12 +3,10 @@
|
|||||||
package libpod
|
package libpod
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/containers/libpod/libpod/define"
|
"github.com/containers/libpod/libpod/define"
|
||||||
"k8s.io/client-go/tools/remotecommand"
|
"k8s.io/client-go/tools/remotecommand"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, wg *sync.WaitGroup) error {
|
func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, started chan bool) error {
|
||||||
return define.ErrNotImplemented
|
return define.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,10 @@ var (
|
|||||||
DefaultSHMLockPath = "/libpod_lock"
|
DefaultSHMLockPath = "/libpod_lock"
|
||||||
// DefaultRootlessSHMLockPath is the default path for rootless SHM locks
|
// DefaultRootlessSHMLockPath is the default path for rootless SHM locks
|
||||||
DefaultRootlessSHMLockPath = "/libpod_rootless_lock"
|
DefaultRootlessSHMLockPath = "/libpod_rootless_lock"
|
||||||
|
|
||||||
|
// DefaultDetachKeys is the default keys sequence for detaching a
|
||||||
|
// container
|
||||||
|
DefaultDetachKeys = "ctrl-p,ctrl-q"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A RuntimeOption is a functional option which alters the Runtime created by
|
// A RuntimeOption is a functional option which alters the Runtime created by
|
||||||
@ -236,6 +240,8 @@ type RuntimeConfig struct {
|
|||||||
EventsLogger string `toml:"events_logger"`
|
EventsLogger string `toml:"events_logger"`
|
||||||
// EventsLogFilePath is where the events log is stored.
|
// EventsLogFilePath is where the events log is stored.
|
||||||
EventsLogFilePath string `toml:-"events_logfile_path"`
|
EventsLogFilePath string `toml:-"events_logfile_path"`
|
||||||
|
//DetachKeys is the sequence of keys used to detach a container
|
||||||
|
DetachKeys string `toml:"detach_keys"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// runtimeConfiguredFrom is a struct used during early runtime init to help
|
// runtimeConfiguredFrom is a struct used during early runtime init to help
|
||||||
@ -308,6 +314,7 @@ func defaultRuntimeConfig() (RuntimeConfig, error) {
|
|||||||
EnableLabeling: true,
|
EnableLabeling: true,
|
||||||
NumLocks: 2048,
|
NumLocks: 2048,
|
||||||
EventsLogger: events.DefaultEventerType.String(),
|
EventsLogger: events.DefaultEventerType.String(),
|
||||||
|
DetachKeys: DefaultDetachKeys,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,8 +384,18 @@ func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config, err := r.Runtime.GetConfig()
|
||||||
|
if err != nil {
|
||||||
|
return exitCode, err
|
||||||
|
}
|
||||||
|
detachKeys := c.String("detach-keys")
|
||||||
|
if detachKeys == "" {
|
||||||
|
detachKeys = config.DetachKeys
|
||||||
|
}
|
||||||
|
|
||||||
// if the container was created as part of a pod, also start its dependencies, if any.
|
// if the container was created as part of a pod, also start its dependencies, if any.
|
||||||
if err := StartAttachCtr(ctx, ctr, outputStream, errorStream, inputStream, c.String("detach-keys"), c.Bool("sig-proxy"), true, c.IsSet("pod")); err != nil {
|
if err := StartAttachCtr(ctx, ctr, outputStream, errorStream, inputStream, detachKeys, c.Bool("sig-proxy"), true, c.IsSet("pod")); err != nil {
|
||||||
// We've manually detached from the container
|
// We've manually detached from the container
|
||||||
// Do not perform cleanup, or wait for container exit code
|
// Do not perform cleanup, or wait for container exit code
|
||||||
// Just exit immediately
|
// Just exit immediately
|
||||||
@ -410,10 +420,6 @@ func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode
|
|||||||
if errors.Cause(err) == define.ErrNoSuchCtr {
|
if errors.Cause(err) == define.ErrNoSuchCtr {
|
||||||
// The container may have been removed
|
// The container may have been removed
|
||||||
// Go looking for an exit file
|
// Go looking for an exit file
|
||||||
config, err := r.Runtime.GetConfig()
|
|
||||||
if err != nil {
|
|
||||||
return exitCode, err
|
|
||||||
}
|
|
||||||
ctrExitCode, err := ReadExitFile(config.TmpDir, ctr.ID())
|
ctrExitCode, err := ReadExitFile(config.TmpDir, ctr.ID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Cannot get exit code: %v", err)
|
logrus.Errorf("Cannot get exit code: %v", err)
|
||||||
|
@ -59,11 +59,6 @@ var ErrDetach = errors.New("detached from container")
|
|||||||
|
|
||||||
// CopyDetachable is similar to io.Copy but support a detach key sequence to break out.
|
// CopyDetachable is similar to io.Copy but support a detach key sequence to break out.
|
||||||
func CopyDetachable(dst io.Writer, src io.Reader, keys []byte) (written int64, err error) {
|
func CopyDetachable(dst io.Writer, src io.Reader, keys []byte) (written int64, err error) {
|
||||||
if len(keys) == 0 {
|
|
||||||
// Default keys : ctrl-p,ctrl-q
|
|
||||||
keys = []byte{16, 17}
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := make([]byte, 32*1024)
|
buf := make([]byte, 32*1024)
|
||||||
for {
|
for {
|
||||||
nr, er := src.Read(buf)
|
nr, er := src.Read(buf)
|
||||||
|
Reference in New Issue
Block a user