修正shell判定
parent
55ad1d0d8a
commit
ce7a67f4d0
@ -0,0 +1,161 @@
|
|||||||
|
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)
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
|
package starainrt
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
func (starcli *StarShell) SetRunUser(uid, gid uint32) {
|
||||||
|
starcli.cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
Credential: &syscall.Credential{
|
||||||
|
Uid: uid,
|
||||||
|
Gid: gid,
|
||||||
|
},
|
||||||
|
Setsid: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (starcli *StarShell) Release() error {
|
||||||
|
if err := starcli.cmd.Start(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
starcli.cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
Setsid: true,
|
||||||
|
}
|
||||||
|
starcli.cmd.Process.Release()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (starcli *StarShell) SetKeepCaps() error {
|
||||||
|
_, _, err := syscall.RawSyscall(157 /*SYS PRCTL */, 0x8 /*PR SET KEEPCAPS*/, 1, 0)
|
||||||
|
if 0 != err {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package starainrt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Starshell(t *testing.T) {
|
||||||
|
star, err := NewStarShell("cmd.exe")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
star.WriteCmd("chcp 65001")
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
star.WriteCmd("ping baidu.com -n 10")
|
||||||
|
time.Sleep(time.Second * 12)
|
||||||
|
star.WriteCmd("exit")
|
||||||
|
}()
|
||||||
|
for star.IsRunning() {
|
||||||
|
time.Sleep(time.Millisecond * 100)
|
||||||
|
str, err := star.GetResult()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("error:", err)
|
||||||
|
}
|
||||||
|
fmt.Print(str)
|
||||||
|
}
|
||||||
|
fmt.Println(star.ExitCode())
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Starbash(t *testing.T) {
|
||||||
|
star, err := NewStarShell("bash", "-c", "ping baidu.com -c 10")
|
||||||
|
err = star.Start()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
go func() {
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
star.WriteCmd("chcp 65001")
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
star.WriteCmd("ping baidu.com -n 10")
|
||||||
|
time.Sleep(time.Second * 12)
|
||||||
|
star.WriteCmd("exit")
|
||||||
|
}()
|
||||||
|
*/
|
||||||
|
for star.IsRunning() {
|
||||||
|
time.Sleep(time.Millisecond * 100)
|
||||||
|
str, err := star.GetResult()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("error:", err)
|
||||||
|
}
|
||||||
|
fmt.Print(str)
|
||||||
|
}
|
||||||
|
fmt.Println(star.ExitCode())
|
||||||
|
}
|
Loading…
Reference in New Issue