本文整理汇总了Golang中github.com/docker/docker/pkg/signal.StopCatch函数的典型用法代码示例。如果您正苦于以下问题:Golang StopCatch函数的具体用法?Golang StopCatch怎么用?Golang StopCatch使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了StopCatch函数的13个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。
示例1: CmdRun
// CmdRun runs a command in a new container.
//
// Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
func (cli *DockerCli) CmdRun(args ...string) error {
cmd := cli.Subcmd("run", []string{"IMAGE [COMMAND] [ARG...]"}, "Run a command in a new container", true)
// These are flags not stored in Config/HostConfig
var (
flAutoRemove = cmd.Bool([]string{"-rm"}, false, "Automatically remove the container when it exits")
flDetach = cmd.Bool([]string{"d", "-detach"}, false, "Run container in background and print container ID")
flSigProxy = cmd.Bool([]string{"-sig-proxy"}, true, "Proxy received signals to the process")
flName = cmd.String([]string{"-name"}, "", "Assign a name to the container")
flAttach *opts.ListOpts
ErrConflictAttachDetach = fmt.Errorf("Conflicting options: -a and -d")
ErrConflictRestartPolicyAndAutoRemove = fmt.Errorf("Conflicting options: --restart and --rm")
ErrConflictDetachAutoRemove = fmt.Errorf("Conflicting options: --rm and -d")
)
config, hostConfig, cmd, err := runconfig.Parse(cmd, args)
// just in case the Parse does not exit
if err != nil {
cmd.ReportError(err.Error(), true)
os.Exit(1)
}
if len(hostConfig.Dns) > 0 {
// check the DNS settings passed via --dns against
// localhost regexp to warn if they are trying to
// set a DNS to a localhost address
for _, dnsIP := range hostConfig.Dns {
if dns.IsLocalhost(dnsIP) {
fmt.Fprintf(cli.err, "WARNING: Localhost DNS setting (--dns=%s) may fail in containers.\n", dnsIP)
break
}
}
}
if config.Image == "" {
cmd.Usage()
return nil
}
if !*flDetach {
if err := cli.CheckTtyInput(config.AttachStdin, config.Tty); err != nil {
return err
}
} else {
if fl := cmd.Lookup("-attach"); fl != nil {
flAttach = fl.Value.(*opts.ListOpts)
if flAttach.Len() != 0 {
return ErrConflictAttachDetach
}
}
if *flAutoRemove {
return ErrConflictDetachAutoRemove
}
config.AttachStdin = false
config.AttachStdout = false
config.AttachStderr = false
config.StdinOnce = false
}
// Disable flSigProxy when in TTY mode
sigProxy := *flSigProxy
if config.Tty {
sigProxy = false
}
// Telling the Windows daemon the initial size of the tty during start makes
// a far better user experience rather than relying on subsequent resizes
// to cause things to catch up.
if runtime.GOOS == "windows" {
hostConfig.ConsoleSize[0], hostConfig.ConsoleSize[1] = cli.getTtySize()
}
createResponse, err := cli.createContainer(config, hostConfig, hostConfig.ContainerIDFile, *flName)
if err != nil {
return err
}
if sigProxy {
sigc := cli.forwardAllSignals(createResponse.ID)
defer signal.StopCatch(sigc)
}
var (
waitDisplayID chan struct{}
errCh chan error
)
if !config.AttachStdout && !config.AttachStderr {
// Make this asynchronous to allow the client to write to stdin before having to read the ID
waitDisplayID = make(chan struct{})
go func() {
defer close(waitDisplayID)
fmt.Fprintf(cli.out, "%s\n", createResponse.ID)
}()
}
if *flAutoRemove && (hostConfig.RestartPolicy.IsAlways() || hostConfig.RestartPolicy.IsOnFailure()) {
return ErrConflictRestartPolicyAndAutoRemove
}
// We need to instantiate the chan because the select needs it. It can
//.........这里部分代码省略.........
示例2: runStart
func runStart(dockerCli *command.DockerCli, opts *startOptions) error {
ctx, cancelFun := context.WithCancel(context.Background())
if opts.attach || opts.openStdin {
// We're going to attach to a container.
// 1. Ensure we only have one container.
if len(opts.containers) > 1 {
return fmt.Errorf("You cannot start and attach multiple containers at once.")
}
// 2. Attach to the container.
container := opts.containers[0]
c, err := dockerCli.Client().ContainerInspect(ctx, container)
if err != nil {
return err
}
// We always use c.ID instead of container to maintain consistency during `docker start`
if !c.Config.Tty {
sigc := ForwardAllSignals(ctx, dockerCli, c.ID)
defer signal.StopCatch(sigc)
}
if opts.detachKeys != "" {
dockerCli.ConfigFile().DetachKeys = opts.detachKeys
}
options := types.ContainerAttachOptions{
Stream: true,
Stdin: opts.openStdin && c.Config.OpenStdin,
Stdout: true,
Stderr: true,
DetachKeys: dockerCli.ConfigFile().DetachKeys,
}
var in io.ReadCloser
if options.Stdin {
in = dockerCli.In()
}
resp, errAttach := dockerCli.Client().ContainerAttach(ctx, c.ID, options)
if errAttach != nil && errAttach != httputil.ErrPersistEOF {
// ContainerAttach return an ErrPersistEOF (connection closed)
// means server met an error and already put it in Hijacked connection,
// we would keep the error and read the detailed error message from hijacked connection
return errAttach
}
defer resp.Close()
cErr := promise.Go(func() error {
errHijack := holdHijackedConnection(ctx, dockerCli, c.Config.Tty, in, dockerCli.Out(), dockerCli.Err(), resp)
if errHijack == nil {
return errAttach
}
return errHijack
})
// 3. We should open a channel for receiving status code of the container
// no matter it's detached, removed on daemon side(--rm) or exit normally.
statusChan, statusErr := waitExitOrRemoved(dockerCli, context.Background(), c.ID, c.HostConfig.AutoRemove)
startOptions := types.ContainerStartOptions{
CheckpointID: opts.checkpoint,
}
// 4. Start the container.
if err := dockerCli.Client().ContainerStart(ctx, c.ID, startOptions); err != nil {
cancelFun()
<-cErr
if c.HostConfig.AutoRemove && statusErr == nil {
// wait container to be removed
<-statusChan
}
return err
}
// 5. Wait for attachment to break.
if c.Config.Tty && dockerCli.Out().IsTerminal() {
if err := MonitorTtySize(ctx, dockerCli, c.ID, false); err != nil {
fmt.Fprintf(dockerCli.Err(), "Error monitoring TTY size: %s\n", err)
}
}
if attchErr := <-cErr; attchErr != nil {
return attchErr
}
if statusErr != nil {
return fmt.Errorf("can't get container's exit code: %v", statusErr)
}
if status := <-statusChan; status != 0 {
return cli.StatusError{StatusCode: status}
}
} else if opts.checkpoint != "" {
if len(opts.containers) > 1 {
return fmt.Errorf("You cannot restore multiple containers at once.")
}
container := opts.containers[0]
startOptions := types.ContainerStartOptions{
CheckpointID: opts.checkpoint,
}
//.........这里部分代码省略.........
示例3: runRun
func runRun(dockerCli *command.DockerCli, flags *pflag.FlagSet, opts *runOptions, copts *containerOptions) error {
stdout, stderr, stdin := dockerCli.Out(), dockerCli.Err(), dockerCli.In()
client := dockerCli.Client()
// TODO: pass this as an argument
cmdPath := "run"
var (
flAttach *opttypes.ListOpts
ErrConflictAttachDetach = errors.New("Conflicting options: -a and -d")
ErrConflictRestartPolicyAndAutoRemove = errors.New("Conflicting options: --restart and --rm")
)
config, hostConfig, networkingConfig, err := parse(flags, copts)
// just in case the parse does not exit
if err != nil {
reportError(stderr, cmdPath, err.Error(), true)
return cli.StatusError{StatusCode: 125}
}
if hostConfig.AutoRemove && !hostConfig.RestartPolicy.IsNone() {
return ErrConflictRestartPolicyAndAutoRemove
}
if hostConfig.OomKillDisable != nil && *hostConfig.OomKillDisable && hostConfig.Memory == 0 {
fmt.Fprintln(stderr, "WARNING: Disabling the OOM killer on containers without setting a '-m/--memory' limit may be dangerous.")
}
if len(hostConfig.DNS) > 0 {
// check the DNS settings passed via --dns against
// localhost regexp to warn if they are trying to
// set a DNS to a localhost address
for _, dnsIP := range hostConfig.DNS {
if dns.IsLocalhost(dnsIP) {
fmt.Fprintf(stderr, "WARNING: Localhost DNS setting (--dns=%s) may fail in containers.\n", dnsIP)
break
}
}
}
config.ArgsEscaped = false
if !opts.detach {
if err := dockerCli.In().CheckTty(config.AttachStdin, config.Tty); err != nil {
return err
}
} else {
if fl := flags.Lookup("attach"); fl != nil {
flAttach = fl.Value.(*opttypes.ListOpts)
if flAttach.Len() != 0 {
return ErrConflictAttachDetach
}
}
config.AttachStdin = false
config.AttachStdout = false
config.AttachStderr = false
config.StdinOnce = false
}
// Disable sigProxy when in TTY mode
if config.Tty {
opts.sigProxy = false
}
// Telling the Windows daemon the initial size of the tty during start makes
// a far better user experience rather than relying on subsequent resizes
// to cause things to catch up.
if runtime.GOOS == "windows" {
hostConfig.ConsoleSize[0], hostConfig.ConsoleSize[1] = dockerCli.Out().GetTtySize()
}
ctx, cancelFun := context.WithCancel(context.Background())
createResponse, err := createContainer(ctx, dockerCli, config, hostConfig, networkingConfig, hostConfig.ContainerIDFile, opts.name)
if err != nil {
reportError(stderr, cmdPath, err.Error(), true)
return runStartContainerErr(err)
}
if opts.sigProxy {
sigc := ForwardAllSignals(ctx, dockerCli, createResponse.ID)
defer signal.StopCatch(sigc)
}
var (
waitDisplayID chan struct{}
errCh chan error
)
if !config.AttachStdout && !config.AttachStderr {
// Make this asynchronous to allow the client to write to stdin before having to read the ID
waitDisplayID = make(chan struct{})
go func() {
defer close(waitDisplayID)
fmt.Fprintln(stdout, createResponse.ID)
}()
}
attach := config.AttachStdin || config.AttachStdout || config.AttachStderr
if attach {
var (
out, cerr io.Writer
in io.ReadCloser
)
//.........这里部分代码省略.........
示例4: runAttach
func runAttach(dockerCli *client.DockerCli, opts *attachOptions) error {
ctx := context.Background()
c, err := dockerCli.Client().ContainerInspect(ctx, opts.container)
if err != nil {
return err
}
if !c.State.Running {
return fmt.Errorf("You cannot attach to a stopped container, start it first")
}
if c.State.Paused {
return fmt.Errorf("You cannot attach to a paused container, unpause it first")
}
if err := dockerCli.CheckTtyInput(!opts.noStdin, c.Config.Tty); err != nil {
return err
}
if opts.detachKeys != "" {
dockerCli.ConfigFile().DetachKeys = opts.detachKeys
}
options := types.ContainerAttachOptions{
Stream: true,
Stdin: !opts.noStdin && c.Config.OpenStdin,
Stdout: true,
Stderr: true,
DetachKeys: dockerCli.ConfigFile().DetachKeys,
}
var in io.ReadCloser
if options.Stdin {
in = dockerCli.In()
}
if opts.proxy && !c.Config.Tty {
sigc := dockerCli.ForwardAllSignals(ctx, opts.container)
defer signal.StopCatch(sigc)
}
resp, errAttach := dockerCli.Client().ContainerAttach(ctx, opts.container, options)
if errAttach != nil && errAttach != httputil.ErrPersistEOF {
// ContainerAttach returns an ErrPersistEOF (connection closed)
// means server met an error and put it in Hijacked connection
// keep the error and read detailed error message from hijacked connection later
return errAttach
}
defer resp.Close()
if c.Config.Tty && dockerCli.IsTerminalOut() {
height, width := dockerCli.GetTtySize()
// To handle the case where a user repeatedly attaches/detaches without resizing their
// terminal, the only way to get the shell prompt to display for attaches 2+ is to artificially
// resize it, then go back to normal. Without this, every attach after the first will
// require the user to manually resize or hit enter.
dockerCli.ResizeTtyTo(ctx, opts.container, height+1, width+1, false)
// After the above resizing occurs, the call to MonitorTtySize below will handle resetting back
// to the actual size.
if err := dockerCli.MonitorTtySize(ctx, opts.container, false); err != nil {
logrus.Debugf("Error monitoring TTY size: %s", err)
}
}
if err := dockerCli.HoldHijackedConnection(ctx, c.Config.Tty, in, dockerCli.Out(), dockerCli.Err(), resp); err != nil {
return err
}
if errAttach != nil {
return errAttach
}
_, status, err := getExitCode(dockerCli, ctx, opts.container)
if err != nil {
return err
}
if status != 0 {
return cli.StatusError{StatusCode: status}
}
return nil
}
示例5: CmdStart
// CmdStart starts one or more containers.
//
// Usage: docker start [OPTIONS] CONTAINER [CONTAINER...]
func (cli *DockerCli) CmdStart(args ...string) error {
cmd := Cli.Subcmd("start", []string{"CONTAINER [CONTAINER...]"}, Cli.DockerCommands["start"].Description, true)
attach := cmd.Bool([]string{"a", "-attach"}, false, "Attach STDOUT/STDERR and forward signals")
openStdin := cmd.Bool([]string{"i", "-interactive"}, false, "Attach container's STDIN")
detachKeys := cmd.String([]string{"-detach-keys"}, "", "Override the key sequence for detaching a container")
cmd.Require(flag.Min, 1)
cmd.ParseFlags(args, true)
ctx, cancelFun := context.WithCancel(context.Background())
if *attach || *openStdin {
// We're going to attach to a container.
// 1. Ensure we only have one container.
if cmd.NArg() > 1 {
return fmt.Errorf("You cannot start and attach multiple containers at once.")
}
// 2. Attach to the container.
container := cmd.Arg(0)
c, err := cli.client.ContainerInspect(ctx, container)
if err != nil {
return err
}
if !c.Config.Tty {
sigc := cli.forwardAllSignals(ctx, container)
defer signal.StopCatch(sigc)
}
if *detachKeys != "" {
cli.configFile.DetachKeys = *detachKeys
}
options := types.ContainerAttachOptions{
Stream: true,
Stdin: *openStdin && c.Config.OpenStdin,
Stdout: true,
Stderr: true,
DetachKeys: cli.configFile.DetachKeys,
}
var in io.ReadCloser
if options.Stdin {
in = cli.in
}
resp, errAttach := cli.client.ContainerAttach(ctx, container, options)
if errAttach != nil && errAttach != httputil.ErrPersistEOF {
// ContainerAttach return an ErrPersistEOF (connection closed)
// means server met an error and put it in Hijacked connection
// keep the error and read detailed error message from hijacked connection
return errAttach
}
defer resp.Close()
cErr := promise.Go(func() error {
errHijack := cli.holdHijackedConnection(ctx, c.Config.Tty, in, cli.out, cli.err, resp)
if errHijack == nil {
return errAttach
}
return errHijack
})
// 3. Start the container.
if err := cli.client.ContainerStart(ctx, container); err != nil {
cancelFun()
<-cErr
return err
}
// 4. Wait for attachment to break.
if c.Config.Tty && cli.isTerminalOut {
if err := cli.monitorTtySize(ctx, container, false); err != nil {
fmt.Fprintf(cli.err, "Error monitoring TTY size: %s\n", err)
}
}
if attchErr := <-cErr; attchErr != nil {
return attchErr
}
_, status, err := cli.getExitCode(ctx, container)
if err != nil {
return err
}
if status != 0 {
return Cli.StatusError{StatusCode: status}
}
} else {
// We're not going to attach to anything.
// Start as many containers as we want.
return cli.startContainersWithoutAttachments(ctx, cmd.Args())
}
return nil
}
示例6: CmdAttach
// CmdAttach attaches to a running container.
//
// Usage: docker attach [OPTIONS] CONTAINER
func (cli *DockerCli) CmdAttach(args ...string) error {
var (
cmd = cli.Subcmd("attach", "CONTAINER", "Attach to a running container", true)
noStdin = cmd.Bool([]string{"#nostdin", "-no-stdin"}, false, "Do not attach STDIN")
proxy = cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxy all received signals to the process")
)
cmd.Require(flag.Exact, 1)
cmd.ParseFlags(args, true)
name := cmd.Arg(0)
stream, _, _, err := cli.call("GET", "/containers/"+name+"/json", nil, nil)
if err != nil {
return err
}
var c types.ContainerJSON
if err := json.NewDecoder(stream).Decode(&c); err != nil {
return err
}
if !c.State.Running {
return fmt.Errorf("You cannot attach to a stopped container, start it first")
}
if err := cli.CheckTtyInput(!*noStdin, c.Config.Tty); err != nil {
return err
}
if c.Config.Tty && cli.isTerminalOut {
if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil {
logrus.Debugf("Error monitoring TTY size: %s", err)
}
}
var in io.ReadCloser
v := url.Values{}
v.Set("stream", "1")
if !*noStdin && c.Config.OpenStdin {
v.Set("stdin", "1")
in = cli.in
}
v.Set("stdout", "1")
v.Set("stderr", "1")
if *proxy && !c.Config.Tty {
sigc := cli.forwardAllSignals(cmd.Arg(0))
defer signal.StopCatch(sigc)
}
if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), c.Config.Tty, in, cli.out, cli.err, nil, nil); err != nil {
return err
}
_, status, err := getExitCode(cli, cmd.Arg(0))
if err != nil {
return err
}
if status != 0 {
return StatusError{StatusCode: status}
}
return nil
}
示例7: CmdRun
// CmdRun runs a command in a new container.
//
// Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
func (cli *DockerCli) CmdRun(args ...string) error {
cmd := Cli.Subcmd("run", []string{"IMAGE [COMMAND] [ARG...]"}, Cli.DockerCommands["run"].Description, true)
addTrustedFlags(cmd, true)
// These are flags not stored in Config/HostConfig
var (
flAutoRemove = cmd.Bool([]string{"-rm"}, false, "Automatically remove the container when it exits")
flDetach = cmd.Bool([]string{"d", "-detach"}, false, "Run container in background and print container ID")
flSigProxy = cmd.Bool([]string{"-sig-proxy"}, true, "Proxy received signals to the process")
flName = cmd.String([]string{"-name"}, "", "Assign a name to the container")
flDetachKeys = cmd.String([]string{"-detach-keys"}, "", "Override the key sequence for detaching a container")
flAttach *opts.ListOpts
ErrConflictAttachDetach = fmt.Errorf("Conflicting options: -a and -d")
ErrConflictRestartPolicyAndAutoRemove = fmt.Errorf("Conflicting options: --restart and --rm")
ErrConflictDetachAutoRemove = fmt.Errorf("Conflicting options: --rm and -d")
)
config, hostConfig, cmd, err := runconfig.Parse(cmd, args)
// just in case the Parse does not exit
if err != nil {
cmd.ReportError(err.Error(), true)
os.Exit(125)
}
if hostConfig.OomKillDisable && hostConfig.Memory == 0 {
fmt.Fprintf(cli.err, "WARNING: Dangerous only disable the OOM Killer on containers but not set the '-m/--memory' option\n")
}
if len(hostConfig.DNS) > 0 {
// check the DNS settings passed via --dns against
// localhost regexp to warn if they are trying to
// set a DNS to a localhost address
for _, dnsIP := range hostConfig.DNS {
if dns.IsLocalhost(dnsIP) {
fmt.Fprintf(cli.err, "WARNING: Localhost DNS setting (--dns=%s) may fail in containers.\n", dnsIP)
break
}
}
}
if config.Image == "" {
cmd.Usage()
return nil
}
config.ArgsEscaped = false
if !*flDetach {
if err := cli.CheckTtyInput(config.AttachStdin, config.Tty); err != nil {
return err
}
} else {
if fl := cmd.Lookup("-attach"); fl != nil {
flAttach = fl.Value.(*opts.ListOpts)
if flAttach.Len() != 0 {
return ErrConflictAttachDetach
}
}
if *flAutoRemove {
return ErrConflictDetachAutoRemove
}
config.AttachStdin = false
config.AttachStdout = false
config.AttachStderr = false
config.StdinOnce = false
}
// Disable flSigProxy when in TTY mode
sigProxy := *flSigProxy
if config.Tty {
sigProxy = false
}
// Telling the Windows daemon the initial size of the tty during start makes
// a far better user experience rather than relying on subsequent resizes
// to cause things to catch up.
if runtime.GOOS == "windows" {
hostConfig.ConsoleSize[0], hostConfig.ConsoleSize[1] = cli.getTtySize()
}
createResponse, err := cli.createContainer(config, hostConfig, hostConfig.ContainerIDFile, *flName)
if err != nil {
cmd.ReportError(err.Error(), true)
return runStartContainerErr(err)
}
if sigProxy {
sigc := cli.forwardAllSignals(createResponse.ID)
defer signal.StopCatch(sigc)
}
var (
waitDisplayID chan struct{}
errCh chan error
)
if !config.AttachStdout && !config.AttachStderr {
// Make this asynchronous to allow the client to write to stdin before having to read the ID
waitDisplayID = make(chan struct{})
//.........这里部分代码省略.........
示例8: runStart
func runStart(dockerCli *client.DockerCli, opts *startOptions) error {
ctx, cancelFun := context.WithCancel(context.Background())
if opts.attach || opts.openStdin {
// We're going to attach to a container.
// 1. Ensure we only have one container.
if len(opts.containers) > 1 {
return fmt.Errorf("You cannot start and attach multiple containers at once.")
}
// 2. Attach to the container.
container := opts.containers[0]
c, err := dockerCli.Client().ContainerInspect(ctx, container)
if err != nil {
return err
}
// We always use c.ID instead of container to maintain consistency during `docker start`
if !c.Config.Tty {
sigc := dockerCli.ForwardAllSignals(ctx, c.ID)
defer signal.StopCatch(sigc)
}
if opts.detachKeys != "" {
dockerCli.ConfigFile().DetachKeys = opts.detachKeys
}
options := types.ContainerAttachOptions{
Stream: true,
Stdin: opts.openStdin && c.Config.OpenStdin,
Stdout: true,
Stderr: true,
DetachKeys: dockerCli.ConfigFile().DetachKeys,
}
var in io.ReadCloser
if options.Stdin {
in = dockerCli.In()
}
resp, errAttach := dockerCli.Client().ContainerAttach(ctx, c.ID, options)
if errAttach != nil && errAttach != httputil.ErrPersistEOF {
// ContainerAttach return an ErrPersistEOF (connection closed)
// means server met an error and put it in Hijacked connection
// keep the error and read detailed error message from hijacked connection
return errAttach
}
defer resp.Close()
cErr := promise.Go(func() error {
errHijack := dockerCli.HoldHijackedConnection(ctx, c.Config.Tty, in, dockerCli.Out(), dockerCli.Err(), resp)
if errHijack == nil {
return errAttach
}
return errHijack
})
// 3. Start the container.
if err := dockerCli.Client().ContainerStart(ctx, c.ID, types.ContainerStartOptions{}); err != nil {
cancelFun()
<-cErr
return err
}
// 4. Wait for attachment to break.
if c.Config.Tty && dockerCli.IsTerminalOut() {
if err := dockerCli.MonitorTtySize(ctx, c.ID, false); err != nil {
fmt.Fprintf(dockerCli.Err(), "Error monitoring TTY size: %s\n", err)
}
}
if attchErr := <-cErr; attchErr != nil {
return attchErr
}
_, status, err := getExitCode(dockerCli, ctx, c.ID)
if err != nil {
return err
}
if status != 0 {
return cli.StatusError{StatusCode: status}
}
} else {
// We're not going to attach to anything.
// Start as many containers as we want.
return startContainersWithoutAttachments(dockerCli, ctx, opts.containers)
}
return nil
}
示例9: CmdAttach
// CmdAttach attaches to a running container.
//
// Usage: docker attach [OPTIONS] CONTAINER
func (cli *DockerCli) CmdAttach(args ...string) error {
cmd := Cli.Subcmd("attach", []string{"CONTAINER"}, Cli.DockerCommands["attach"].Description, true)
noStdin := cmd.Bool([]string{"-no-stdin"}, false, "Do not attach STDIN")
proxy := cmd.Bool([]string{"-sig-proxy"}, true, "Proxy all received signals to the process")
detachKeys := cmd.String([]string{"-detach-keys"}, "", "Override the key sequence for detaching a container")
cmd.Require(flag.Exact, 1)
cmd.ParseFlags(args, true)
c, err := cli.client.ContainerInspect(context.Background(), cmd.Arg(0))
if err != nil {
return err
}
if !c.State.Running {
return fmt.Errorf("You cannot attach to a stopped container, start it first")
}
if c.State.Paused {
return fmt.Errorf("You cannot attach to a paused container, unpause it first")
}
if err := cli.CheckTtyInput(!*noStdin, c.Config.Tty); err != nil {
return err
}
if *detachKeys != "" {
cli.configFile.DetachKeys = *detachKeys
}
container := cmd.Arg(0)
options := types.ContainerAttachOptions{
Stream: true,
Stdin: !*noStdin && c.Config.OpenStdin,
Stdout: true,
Stderr: true,
DetachKeys: cli.configFile.DetachKeys,
}
var in io.ReadCloser
if options.Stdin {
in = cli.in
}
if *proxy && !c.Config.Tty {
sigc := cli.forwardAllSignals(container)
defer signal.StopCatch(sigc)
}
resp, errAttach := cli.client.ContainerAttach(context.Background(), container, options)
if errAttach != nil && errAttach != httputil.ErrPersistEOF {
// ContainerAttach returns an ErrPersistEOF (connection closed)
// means server met an error and put it in Hijacked connection
// keep the error and read detailed error message from hijacked connection later
return errAttach
}
defer resp.Close()
if c.Config.Tty && cli.isTerminalOut {
height, width := cli.getTtySize()
// To handle the case where a user repeatedly attaches/detaches without resizing their
// terminal, the only way to get the shell prompt to display for attaches 2+ is to artificially
// resize it, then go back to normal. Without this, every attach after the first will
// require the user to manually resize or hit enter.
cli.resizeTtyTo(cmd.Arg(0), height+1, width+1, false)
// After the above resizing occurs, the call to monitorTtySize below will handle resetting back
// to the actual size.
if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil {
logrus.Debugf("Error monitoring TTY size: %s", err)
}
}
if err := cli.holdHijackedConnection(context.Background(), c.Config.Tty, in, cli.out, cli.err, resp); err != nil {
return err
}
if errAttach != nil {
return errAttach
}
_, status, err := getExitCode(cli, container)
if err != nil {
return err
}
if status != 0 {
return Cli.StatusError{StatusCode: status}
}
return nil
}
示例10: CmdStart
// CmdStart starts one or more stopped containers.
//
// Usage: docker start [OPTIONS] CONTAINER [CONTAINER...]
func (cli *DockerCli) CmdStart(args ...string) error {
var (
cErr chan error
tty bool
cmd = cli.Subcmd("start", "CONTAINER [CONTAINER...]", "Start one or more stopped containers", true)
attach = cmd.Bool([]string{"a", "-attach"}, false, "Attach STDOUT/STDERR and forward signals")
openStdin = cmd.Bool([]string{"i", "-interactive"}, false, "Attach container's STDIN")
)
cmd.Require(flag.Min, 1)
cmd.ParseFlags(args, true)
if *attach || *openStdin {
if cmd.NArg() > 1 {
return fmt.Errorf("You cannot start and attach multiple containers at once.")
}
stream, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/json", nil, nil)
if err != nil {
return err
}
var c types.ContainerJSON
if err := json.NewDecoder(stream).Decode(&c); err != nil {
return err
}
tty = c.Config.Tty
if !tty {
sigc := cli.forwardAllSignals(cmd.Arg(0))
defer signal.StopCatch(sigc)
}
var in io.ReadCloser
v := url.Values{}
v.Set("stream", "1")
if *openStdin && c.Config.OpenStdin {
v.Set("stdin", "1")
in = cli.in
}
v.Set("stdout", "1")
v.Set("stderr", "1")
hijacked := make(chan io.Closer)
// Block the return until the chan gets closed
defer func() {
logrus.Debugf("CmdStart() returned, defer waiting for hijack to finish.")
if _, ok := <-hijacked; ok {
fmt.Fprintln(cli.err, "Hijack did not finish (chan still open)")
}
cli.in.Close()
}()
cErr = promise.Go(func() error {
return cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), tty, in, cli.out, cli.err, hijacked, nil)
})
// Acknowledge the hijack before starting
select {
case closer := <-hijacked:
// Make sure that the hijack gets closed when returning (results
// in closing the hijack chan and freeing server's goroutines)
if closer != nil {
defer closer.Close()
}
case err := <-cErr:
if err != nil {
return err
}
}
}
var encounteredError error
var errNames []string
for _, name := range cmd.Args() {
_, _, err := readBody(cli.call("POST", "/containers/"+name+"/start", nil, nil))
if err != nil {
if !*attach && !*openStdin {
// attach and openStdin is false means it could be starting multiple containers
// when a container start failed, show the error message and start next
fmt.Fprintf(cli.err, "%s\n", err)
errNames = append(errNames, name)
} else {
encounteredError = err
}
} else {
if !*attach && !*openStdin {
fmt.Fprintf(cli.out, "%s\n", name)
}
}
}
if len(errNames) > 0 {
//.........这里部分代码省略.........
示例11: CmdAttach
// CmdAttach attaches to a running container.
//
// Usage: docker attach [OPTIONS] CONTAINER
func (cli *DockerCli) CmdAttach(args ...string) error {
cmd := Cli.Subcmd("attach", []string{"CONTAINER"}, Cli.DockerCommands["attach"].Description, true)
noStdin := cmd.Bool([]string{"-no-stdin"}, false, "Do not attach STDIN")
proxy := cmd.Bool([]string{"-sig-proxy"}, true, "Proxy all received signals to the process")
cmd.Require(flag.Exact, 1)
cmd.ParseFlags(args, true)
c, err := cli.client.ContainerInspect(cmd.Arg(0))
if err != nil {
return err
}
if !c.State.Running {
return fmt.Errorf("You cannot attach to a stopped container, start it first")
}
if c.State.Paused {
return fmt.Errorf("You cannot attach to a paused container, unpause it first")
}
if err := cli.CheckTtyInput(!*noStdin, c.Config.Tty); err != nil {
return err
}
if c.Config.Tty && cli.isTerminalOut {
if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil {
logrus.Debugf("Error monitoring TTY size: %s", err)
}
}
options := types.ContainerAttachOptions{
ContainerID: cmd.Arg(0),
Stream: true,
Stdin: !*noStdin && c.Config.OpenStdin,
Stdout: true,
Stderr: true,
}
var in io.ReadCloser
if options.Stdin {
in = cli.in
}
if *proxy && !c.Config.Tty {
sigc := cli.forwardAllSignals(options.ContainerID)
defer signal.StopCatch(sigc)
}
resp, err := cli.client.ContainerAttach(options)
if err != nil {
return err
}
defer resp.Close()
if err := cli.holdHijackedConnection(c.Config.Tty, in, cli.out, cli.err, resp); err != nil {
return err
}
_, status, err := getExitCode(cli, options.ContainerID)
if err != nil {
return err
}
if status != 0 {
return Cli.StatusError{StatusCode: status}
}
return nil
}
示例12: CmdStart
// CmdStart starts one or more containers.
//
// Usage: docker start [OPTIONS] CONTAINER [CONTAINER...]
func (cli *DockerCli) CmdStart(args ...string) error {
cmd := Cli.Subcmd("start", []string{"CONTAINER [CONTAINER...]"}, Cli.DockerCommands["start"].Description, true)
attach := cmd.Bool([]string{"a", "-attach"}, false, "Attach STDOUT/STDERR and forward signals")
openStdin := cmd.Bool([]string{"i", "-interactive"}, false, "Attach container's STDIN")
cmd.Require(flag.Min, 1)
cmd.ParseFlags(args, true)
if *attach || *openStdin {
// We're going to attach to a container.
// 1. Ensure we only have one container.
if cmd.NArg() > 1 {
return fmt.Errorf("You cannot start and attach multiple containers at once.")
}
// 2. Attach to the container.
containerID := cmd.Arg(0)
c, err := cli.client.ContainerInspect(containerID)
if err != nil {
return err
}
if !c.Config.Tty {
sigc := cli.forwardAllSignals(containerID)
defer signal.StopCatch(sigc)
}
options := types.ContainerAttachOptions{
ContainerID: containerID,
Stream: true,
Stdin: *openStdin && c.Config.OpenStdin,
Stdout: true,
Stderr: true,
}
var in io.ReadCloser
if options.Stdin {
in = cli.in
}
resp, err := cli.client.ContainerAttach(options)
if err != nil {
return err
}
defer resp.Close()
cErr := promise.Go(func() error {
return cli.holdHijackedConnection(c.Config.Tty, in, cli.out, cli.err, resp)
})
// 3. Start the container.
if err := cli.client.ContainerStart(containerID); err != nil {
return err
}
// 4. Wait for attachment to break.
if c.Config.Tty && cli.isTerminalOut {
if err := cli.monitorTtySize(containerID, false); err != nil {
fmt.Fprintf(cli.err, "Error monitoring TTY size: %s\n", err)
}
}
if attchErr := <-cErr; attchErr != nil {
return attchErr
}
_, status, err := getExitCode(cli, containerID)
if err != nil {
return err
}
if status != 0 {
return Cli.StatusError{StatusCode: status}
}
} else {
// We're not going to attach to anything.
// Start as many containers as we want.
return cli.startContainersWithoutAttachments(cmd.Args())
}
return nil
}
示例13: CmdRun
func (cli *KraneCli) CmdRun(args ...string) error {
// FIXME: just use runconfig.Parse already
cmd := cli.Subcmd("run", "IMAGE [COMMAND] [ARG...]", "Run a command in a new container")
// These are flags not stored in Config/HostConfig
var (
flAutoRemove = cmd.Bool([]string{"#rm", "-rm"}, false, "Automatically remove the container when it exits (incompatible with -d)")
flDetach = cmd.Bool([]string{"d", "-detach"}, false, "Detached mode: run the container in the background and print the new container ID")
flSigProxy = cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxy received signals to the process (even in non-TTY mode). SIGCHLD, SIGSTOP, and SIGKILL are not proxied.")
flName = cmd.String([]string{"#name", "-name"}, "", "Assign a name to the container")
flShip = cmd.String([]string{"ship", "-ship"}, "", "Ship name to deploy at")
flAttach *opts.ListOpts
ErrConflictAttachDetach = fmt.Errorf("Conflicting options: -a and -d")
ErrConflictRestartPolicyAndAutoRemove = fmt.Errorf("Conflicting options: --restart and --rm")
ErrConflictDetachAutoRemove = fmt.Errorf("Conflicting options: --rm and -d")
)
config, hostConfig, cmd, err := runconfig.Parse(cmd, args, nil)
if err != nil {
return err
}
if config.Image == "" || *flShip == "" {
cmd.Usage()
return nil
}
if *flDetach {
if fl := cmd.Lookup("attach"); fl != nil {
flAttach = fl.Value.(*opts.ListOpts)
if flAttach.Len() != 0 {
return ErrConflictAttachDetach
}
}
if *flAutoRemove {
return ErrConflictDetachAutoRemove
}
config.AttachStdin = false
config.AttachStdout = false
config.AttachStderr = false
config.StdinOnce = false
}
// Disable flSigProxy when in TTY mode
sigProxy := *flSigProxy
if config.Tty {
sigProxy = false
}
runResult, err := cli.createContainer(config, hostConfig, hostConfig.ContainerIDFile, *flName, *flShip)
if err != nil {
return err
}
if sigProxy {
sigc := cli.forwardAllSignals(runResult.Get("Id"))
defer signal.StopCatch(sigc)
}
var (
waitDisplayId chan struct{}
errCh chan error
)
if !config.AttachStdout && !config.AttachStderr {
// Make this asynchronous to allow the client to write to stdin before having to read the ID
waitDisplayId = make(chan struct{})
go func() {
defer close(waitDisplayId)
fmt.Fprintf(cli.out, "%s\n", runResult.Get("Id"))
}()
}
if *flAutoRemove && (hostConfig.RestartPolicy.Name == "always" || hostConfig.RestartPolicy.Name == "on-failure") {
return ErrConflictRestartPolicyAndAutoRemove
}
// We need to instantiate the chan because the select needs it. It can
// be closed but can't be uninitialized.
hijacked := make(chan io.Closer)
// Block the return until the chan gets closed
defer func() {
log.Debugf("End of CmdRun(), Waiting for hijack to finish.")
if _, ok := <-hijacked; ok {
log.Errorf("Hijack did not finish (chan still open)")
}
}()
if config.AttachStdin || config.AttachStdout || config.AttachStderr {
var (
out, stderr io.Writer
in io.ReadCloser
v = url.Values{}
)
v.Set("stream", "1")
if config.AttachStdin {
v.Set("stdin", "1")
//.........这里部分代码省略.........