You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
3.3 KiB
Go
162 lines
3.3 KiB
Go
package starainrt
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"io"
|
|
"os"
|
|
"os/exec"
|
|
"syscall"
|
|
"time"
|
|
)
|
|
|
|
type StarShell struct {
|
|
outfile *io.ReadCloser
|
|
infile *io.WriteCloser
|
|
errfile *io.ReadCloser
|
|
cmd *exec.Cmd
|
|
running bool
|
|
stopSign context.Context
|
|
stopFunc context.CancelFunc
|
|
stdout []byte
|
|
errout []byte
|
|
runerr error
|
|
exitcode int
|
|
}
|
|
|
|
func NewStarShell(command string, args ...string) (*StarShell, error) {
|
|
shell := new(StarShell)
|
|
shell.stopSign, shell.stopFunc = context.WithCancel(context.Background())
|
|
cmd := exec.CommandContext(shell.stopSign, command, args...)
|
|
shell.cmd = cmd
|
|
infile, err := shell.cmd.StdinPipe()
|
|
if err != nil {
|
|
return shell, err
|
|
}
|
|
shell.infile = &infile
|
|
errfile, err := shell.cmd.StderrPipe()
|
|
if err != nil {
|
|
return shell, err
|
|
}
|
|
shell.errfile = &errfile
|
|
outfile, err := shell.cmd.StdoutPipe()
|
|
if err != nil {
|
|
return shell, err
|
|
}
|
|
shell.outfile = &outfile
|
|
shell.runerr = nil
|
|
shell.exitcode = -999
|
|
return shell, nil
|
|
}
|
|
|
|
func (starcli *StarShell) Start() error {
|
|
if err := starcli.cmd.Start(); err != nil {
|
|
return err
|
|
}
|
|
starcli.running = true
|
|
go func() {
|
|
err := starcli.cmd.Wait()
|
|
if err != nil {
|
|
starcli.runerr = err
|
|
}
|
|
starcli.exitcode = starcli.cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
|
|
starcli.running = false
|
|
}()
|
|
go starcli.queryResult()
|
|
go starcli.queryErrResult()
|
|
return nil
|
|
}
|
|
|
|
func (starcli *StarShell) queryResult() error {
|
|
for starcli.running {
|
|
out := make([]byte, 65535)
|
|
n, err := (*starcli.outfile).Read(out)
|
|
if n != 0 {
|
|
for i := 0; i < n; i++ {
|
|
starcli.stdout = append(starcli.stdout, out[i])
|
|
}
|
|
}
|
|
if err != nil {
|
|
if err == io.EOF {
|
|
break
|
|
} else {
|
|
starcli.runerr = err
|
|
return err
|
|
}
|
|
|
|
}
|
|
time.Sleep(time.Microsecond * 100)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (starcli *StarShell) queryErrResult() error {
|
|
for starcli.running {
|
|
out := make([]byte, 65535)
|
|
n, err := (*starcli.errfile).Read(out)
|
|
if n != 0 {
|
|
for i := 0; i < n; i++ {
|
|
starcli.errout = append(starcli.errout, out[i])
|
|
}
|
|
}
|
|
if err != nil {
|
|
if err == io.EOF {
|
|
break
|
|
} else {
|
|
starcli.runerr = err
|
|
return err
|
|
}
|
|
}
|
|
time.Sleep(time.Microsecond * 100)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (starcli *StarShell) GetResult() (string, error) {
|
|
np := len(starcli.stdout)
|
|
res1 := string(starcli.stdout[0:np])
|
|
starcli.stdout = starcli.stdout[np:]
|
|
np = len(starcli.errout)
|
|
res2 := string(starcli.errout[0:np])
|
|
starcli.errout = starcli.errout[np:]
|
|
if len(res2) == 0 && starcli.runerr != nil {
|
|
res2 = starcli.runerr.Error()
|
|
}
|
|
if len(res2) == 0 {
|
|
return res1, nil
|
|
}
|
|
return res1, errors.New(res2)
|
|
}
|
|
|
|
func (starcli *StarShell) Exec(cmd string, wait int) (string, error) {
|
|
(*starcli.infile).Write([]byte(cmd + "\n"))
|
|
time.Sleep(time.Millisecond * time.Duration(wait))
|
|
return starcli.GetResult()
|
|
}
|
|
|
|
func (starcli *StarShell) WriteCmd(cmdstr string) {
|
|
(*starcli.infile).Write([]byte(cmdstr + "\n"))
|
|
return
|
|
}
|
|
|
|
func (starcli *StarShell) ExitCode() int {
|
|
return starcli.exitcode
|
|
}
|
|
|
|
func (starcli *StarShell) Kill() {
|
|
starcli.stopFunc()
|
|
starcli.running = false
|
|
}
|
|
|
|
func (starcli *StarShell) IsRunning() bool {
|
|
return starcli.running
|
|
}
|
|
|
|
func (starcli *StarShell) GetPid() int {
|
|
return starcli.cmd.Process.Pid
|
|
}
|
|
|
|
func (starcli *StarShell) Signal(sig os.Signal) error {
|
|
return starcli.cmd.Process.Signal(sig)
|
|
}
|