commit
5c94544fb8
4 changed files with 212 additions and 1 deletions
94
oci/oci.go
94
oci/oci.go
|
@ -148,6 +148,100 @@ func (r *Runtime) StartContainer(c *Container) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ExecSyncResponse is returned from ExecSync.
|
||||
type ExecSyncResponse struct {
|
||||
Stdout []byte
|
||||
Stderr []byte
|
||||
ExitCode int32
|
||||
}
|
||||
|
||||
// ExecSync execs a command in a container and returns it's stdout, stderr and return code.
|
||||
func (r *Runtime) ExecSync(c *Container, command []string, timeout int64) (resp *ExecSyncResponse, err error) {
|
||||
args := []string{"exec", c.name}
|
||||
args = append(args, command...)
|
||||
cmd := exec.Command(r.Path(), args...)
|
||||
var stdoutBuf, stderrBuf bytes.Buffer
|
||||
cmd.Stdout = &stdoutBuf
|
||||
cmd.Stderr = &stderrBuf
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
return &ExecSyncResponse{
|
||||
Stdout: stdoutBuf.Bytes(),
|
||||
Stderr: stderrBuf.Bytes(),
|
||||
ExitCode: -1,
|
||||
}, err
|
||||
}
|
||||
|
||||
if timeout > 0 {
|
||||
done := make(chan error, 1)
|
||||
go func() {
|
||||
done <- cmd.Wait()
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-time.After(time.Duration(timeout) * time.Second):
|
||||
err = unix.Kill(cmd.Process.Pid, syscall.SIGKILL)
|
||||
if err != nil && err != syscall.ESRCH {
|
||||
return &ExecSyncResponse{
|
||||
Stdout: stdoutBuf.Bytes(),
|
||||
Stderr: stderrBuf.Bytes(),
|
||||
ExitCode: -1,
|
||||
}, fmt.Errorf("failed to kill process on timeout: %v", err)
|
||||
}
|
||||
return &ExecSyncResponse{
|
||||
Stdout: stdoutBuf.Bytes(),
|
||||
Stderr: stderrBuf.Bytes(),
|
||||
ExitCode: -1,
|
||||
}, fmt.Errorf("command timed out")
|
||||
case err = <-done:
|
||||
if err != nil {
|
||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
|
||||
return &ExecSyncResponse{
|
||||
Stdout: stdoutBuf.Bytes(),
|
||||
Stderr: stderrBuf.Bytes(),
|
||||
ExitCode: int32(status.ExitStatus()),
|
||||
}, err
|
||||
}
|
||||
} else {
|
||||
return &ExecSyncResponse{
|
||||
Stdout: stdoutBuf.Bytes(),
|
||||
Stderr: stderrBuf.Bytes(),
|
||||
ExitCode: -1,
|
||||
}, err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
err = cmd.Wait()
|
||||
if err != nil {
|
||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
|
||||
return &ExecSyncResponse{
|
||||
Stdout: stdoutBuf.Bytes(),
|
||||
Stderr: stderrBuf.Bytes(),
|
||||
ExitCode: int32(status.ExitStatus()),
|
||||
}, err
|
||||
}
|
||||
} else {
|
||||
return &ExecSyncResponse{
|
||||
Stdout: stdoutBuf.Bytes(),
|
||||
Stderr: stderrBuf.Bytes(),
|
||||
ExitCode: -1,
|
||||
}, err
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return &ExecSyncResponse{
|
||||
Stdout: stdoutBuf.Bytes(),
|
||||
Stderr: stderrBuf.Bytes(),
|
||||
ExitCode: 0,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// StopContainer stops a container.
|
||||
func (r *Runtime) StopContainer(c *Container) error {
|
||||
if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, "kill", c.name); err != nil {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue