...
1
2
3 package runhcs
4
5 import (
6 "context"
7 "fmt"
8 "path/filepath"
9 "strings"
10
11 irunhcs "github.com/Microsoft/hcsshim/internal/runhcs"
12 "github.com/containerd/go-runc"
13 )
14
15
16 type ExecOpts struct {
17 runc.IO
18
19 Detach bool
20
21 PidFile string
22
23 ShimLog string
24 }
25
26 func (opt *ExecOpts) args() ([]string, error) {
27 var out []string
28 if opt.Detach {
29 out = append(out, "--detach")
30 }
31 if opt.PidFile != "" {
32 abs, err := filepath.Abs(opt.PidFile)
33 if err != nil {
34 return nil, err
35 }
36 out = append(out, "--pid-file", abs)
37 }
38 if opt.ShimLog != "" {
39 if strings.HasPrefix(opt.ShimLog, irunhcs.SafePipePrefix) {
40 out = append(out, "--shim-log", opt.ShimLog)
41 } else {
42 abs, err := filepath.Abs(opt.ShimLog)
43 if err != nil {
44 return nil, err
45 }
46 out = append(out, "--shim-log", abs)
47 }
48 }
49 return out, nil
50 }
51
52
53
54 func (r *Runhcs) Exec(context context.Context, id, processFile string, opts *ExecOpts) error {
55 args := []string{"exec", "--process", processFile}
56 if opts != nil {
57 oargs, err := opts.args()
58 if err != nil {
59 return err
60 }
61 args = append(args, oargs...)
62 }
63 cmd := r.command(context, append(args, id)...)
64 if opts != nil && opts.IO != nil {
65 opts.Set(cmd)
66 }
67 if cmd.Stdout == nil && cmd.Stderr == nil {
68 data, err := cmdOutput(cmd, true)
69 if err != nil {
70 return fmt.Errorf("%s: %s", err, data)
71 }
72 return nil
73 }
74 ec, err := runc.Monitor.Start(cmd)
75 if err != nil {
76 return err
77 }
78 if opts != nil && opts.IO != nil {
79 if c, ok := opts.IO.(runc.StartCloser); ok {
80 if err := c.CloseAfterStart(); err != nil {
81 return err
82 }
83 }
84 }
85 status, err := runc.Monitor.Wait(cmd, ec)
86 if err == nil && status != 0 {
87 err = fmt.Errorf("%s did not terminate successfully", cmd.Args[0])
88 }
89 return err
90 }
91
View as plain text