代码拉取完成,页面将自动刷新
package s
import (
"bytes"
"fmt"
"io"
"log"
"os"
"os/exec"
"path"
"runtime"
"sync"
"time"
"gitee.com/dark.H/go-utils/o"
)
var (
home, _ = os.UserHomeDir()
/* CSTR_EXPECT
set a str expect input bytes if need input within cmd.
*/
CSTR_EXPECT = 0b1000
CSTR_TYPE = 0b0100
CSTR_STDOUT = 0b0001
CSTR_STDIN = 0b0010
/* CSTR_IOINPUT
set use stdinput if need a input within cmd.
*/
CSTR_INTERACT = 0b0011
)
type CStr struct {
Str
startCheck bool
delay int
lock *sync.RWMutex
env Dict[Str, Str]
running Dict[Str, int]
outhistory List[Str]
history List[Str]
}
func (str Str) AsCmd(cdPath ...any) CStr {
c := CStr{
Str: str,
lock: &sync.RWMutex{},
env: make(Dict[Str, Str]),
running: make(Dict[Str, int]),
}
c.env["cwd"] = "."
if cdPath != nil {
c = c.Cd(cdPath[0])
}
return c
}
func (cstr CStr) Self() Str {
s, err := o.Executable()
if err != nil {
SafePushErr(err)
}
return Str(s)
}
func (cstr CStr) DelSelf(delay int) CStr {
d := "rm"
if cstr.Plat().Eq("windows") {
d = "del"
}
cstr.Str = Str(d + " " + string(cstr.Self()))
if delay < 2 {
log.Fatal("delete self must > 2 s")
}
return cstr.Delay(delay).RunDaemon()
}
func (cstr CStr) Plat() Str {
return Str(runtime.GOOS)
}
func (cstr CStr) Cd(path any) CStr {
pathS := Str(".")
if p, ok := path.(string); ok {
pathS = Str(p)
} else if p, ok := path.(Str); ok {
pathS = p
}
if pathS.Has("~") {
pathS = pathS.Replace("~", home)
}
if oldcwd, ok := cstr.env["cwd"]; ok {
if pathS.StartWith("/") && pathS.IsDir() {
cstr.env["cwd"] = pathS
} else if pathS.Has(":\\") && pathS.IsDir() {
cstr.env["cwd"] = pathS
} else {
c := oldcwd.FilePathJoin(pathS)
if c.IsDir() {
cstr.env["cwd"] = c
}
}
} else {
if pathS.IsDir() {
cstr.env["cwd"] = pathS
}
}
return cstr
}
type RWeader struct {
S chan []byte
closed bool
}
func (rw *RWeader) Read(buf []byte) (n int, err error) {
if rw.closed {
return -1, io.EOF
}
if rw == nil {
return -1, io.EOF
}
if rw.S == nil {
return -1, io.EOF
}
e := <-rw.S
n = len(e)
copy(buf[:n], e)
return
}
func (rw *RWeader) Close() error {
if rw.closed {
return nil
}
rw.closed = true
close(rw.S)
return nil
}
func (rw *RWeader) Write(buf []byte) (n int, err error) {
if rw.closed {
return -1, io.EOF
}
if rw == nil {
return -1, io.EOF
}
if rw.S == nil {
return -1, io.EOF
}
n = len(buf)
nb := make([]byte, n)
copy(nb, buf)
rw.S <- nb
return
}
func NewTmpRWer(n int) *RWeader {
return &RWeader{
S: make(chan []byte, n),
closed: false,
}
}
func (cstr CStr) Delay(sec int) CStr {
cstr.delay = sec
return cstr
}
func (cstr CStr) ExecDaemon(cmd string, logPath ...string) CStr {
createLogFile := func(fileName string) (fd *os.File, err error) {
fileName = cstr.env["cwd"].Println().FilePathJoin(fileName).String()
// fmt.Println(fileName)
dir := path.Dir(fileName)
if _, err = os.Stat(dir); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(dir, 0755); err != nil {
log.Println(err)
return
}
}
if fd, err = os.Create(fileName); err != nil {
log.Println(err)
return
}
return
}
// args := List[Str]{}
dargs := []string{}
Str(cmd).Split().Each(func(i int, item Str) {
dargs = append(dargs, item.String())
})
args := List[string]{}
cmdName := ""
if runtime.GOOS == "windows" {
// cmdName = "c:\\windows\\system32\\cmd.exe"
cmdName = Str("288882f38f858987a96da29d94e2db6b936ab86ccc98bccdeff768").HXorHex("key!").String()
if cstr.delay > 0 {
args = append(args, cmdName, "/c", fmt.Sprintf("cd %s & ( ping -n %d localhost && %s )", cstr.env["cwd"], cstr.delay, cmd))
} else {
args = append(args, cmdName, "/c", fmt.Sprintf("cd %s & %s", cstr.env["cwd"], cmd))
}
} else {
cmdName = "/bin/bash"
if cstr.delay > 0 {
args = append(args, cmdName, "-c", fmt.Sprintf("cd %s ; sleep %d ; %s", cstr.env["cwd"], cstr.delay, cmd))
} else {
args = append(args, cmdName, "-c", fmt.Sprintf("cd %s ; %s", cstr.env["cwd"], cmd))
}
}
if logPath != nil {
logFd, err := createLogFile(logPath[0])
if err != nil {
log.Println(err)
SafePushErr(err)
return cstr
}
defer logFd.Close()
newProc, err := os.StartProcess(cmdName, args, &os.ProcAttr{
Files: []*os.File{logFd, logFd, logFd},
})
if err != nil {
log.Println(err)
// log.Fatal(z2.ERR_DAEMON, err)
SafePushErr(err)
return cstr
}
cstr.running[Str(cmd)] = newProc.Pid
if !cstr.startCheck {
go cstr.BackgroundCheckRunning()
cstr.startCheck = true
}
} else {
cmdName := args[0]
poc, err := os.StartProcess(cmdName, args, &os.ProcAttr{
Files: []*os.File{nil, nil, nil},
})
if err != nil {
log.Println(err)
SafePushErr(err)
return cstr
}
// fmt.Println(cmd, poc.Pid)
cstr.running[Str(cmd)] = poc.Pid
if !cstr.startCheck {
go cstr.BackgroundCheckRunning()
cstr.startCheck = true
}
}
return cstr
}
func (cstr CStr) GetProcess() Dict[int, Str] {
process := make(Dict[int, Str])
if runtime.GOOS == "windows" {
cstr.Exec("tasklist").Output().Split("\n")[2:].Each(func(i int, item Str) {
fs1 := item.ReFindAll("[\\w\\.\\s]+?\\s+\\d+")
if fs1.Len() > 0 {
foundPro := fs1[0]
ProPID, err := foundPro.Split().Last().TryAsInt()
if err == nil {
ProName := foundPro.Split().Slice(0, -1).Join()
// ProName.ANSIUnderline().Println(ProPID, ":")
process[ProPID] = Str(ProName)
}
}
})
} else {
cstr.Exec("ps aux").Output().Split("\n")[1:].Each(func(i int, item Str) {
fs := item.Split()
if fs.Len() > 10 {
ProPID, err := fs[1].TryAsInt()
if err == nil {
ProName := fs[9:].Join()
process[ProPID] = ProName
}
}
})
}
return process
}
func (cstr CStr) RunningStatus() Dict[Str, bool] {
ok := make(Dict[Str, bool])
nowProcess := cstr.GetProcess()
cstr.running.Each(func(k Str, proPid int) {
// k.Println(proPid, ":")
// time.Sleep(1 * time.Second)
if pid, name, found := nowProcess.Any(func(v int, k Str) bool {
return proPid == v
}); found {
// deadKeys = append(deadKeys, k)
ok[Sprintf("%s (%d)", name, pid)] = true
}
})
return ok
}
func (cstr CStr) BackgroundCheckRunning() {
tick := time.NewTicker(10 * time.Second)
for {
select {
case <-tick.C:
deadKeys := List[Str]{}
nowProcess := cstr.GetProcess()
cstr.running.Each(func(k Str, proPid int) {
if _, _, found := nowProcess.Any(func(v int, k Str) bool {
return proPid == v
}); found {
deadKeys = append(deadKeys, k)
}
})
cstr.lock.Lock()
deadKeys.Each(func(i int, item Str) {
delete(cstr.running, item)
item.ANSIBold().ANSIUnderline().Println("process dead:")
})
cstr.lock.Unlock()
default:
time.Sleep(10 * time.Second)
}
}
}
func (cstr CStr) Log() CStr {
cstr.Output().Println("log:")
return cstr
}
func (cstr CStr) RunDaemon(logPath ...string) CStr {
return cstr.ExecDaemon(cstr.Str.String(), logPath...)
}
func (cstr CStr) Run(opts ...any) CStr {
return cstr.Exec(string(cstr.Str), opts...)
}
func (cstr CStr) Exec(cmd string, opts ...any) CStr {
// var cmd exec.Cmd
e := List[string]{}
if runtime.GOOS == "windows" {
e = append(e, "c:\\windows\\system32\\cmd.exe", "/c")
if cstr.delay > 0 {
e = append(e, fmt.Sprintf(`cd %s & ( ping -n %d localhost && %s )`, cstr.env["cwd"], cstr.delay, cmd))
// opts = append(opts, CSTR_INTERACT)
} else {
e = append(e, fmt.Sprintf("cd %s & %s", cstr.env["cwd"], cmd))
}
} else {
e = append(e, "bash", "-c")
if cstr.delay > 0 {
e = append(e, fmt.Sprintf("cd %s ; sleep %d ; %s", cstr.env["cwd"], cstr.delay, cmd))
} else {
e = append(e, fmt.Sprintf("cd %s ; %s", cstr.env["cwd"], cmd))
}
}
fmt.Println(e[0], e[1], e[2])
c := exec.Command(e[0], e[1:]...)
bufout := bytes.NewBuffer([]byte{})
errout := bytes.NewBuffer([]byte{})
stdInput := NewTmpRWer(100)
defer stdInput.Close()
Closed := false
mode := 0
expects := make(Dict[Str, Str])
expectStr := ""
var err error
if opts != nil {
setOut := false
for _, opt := range opts {
if optI, ok := opt.(int); ok {
mode |= optI
// fmt.Println("mode:", optI)
if optI&CSTR_INTERACT == CSTR_INTERACT {
c.Stdin = os.Stdin
// bytes.NewReader()
tee := io.MultiWriter(os.Stdout, bufout)
teeerr := io.MultiWriter(os.Stderr, errout)
c.Stdout = tee
c.Stderr = teeerr
setOut = true
break
} else if optI&CSTR_STDOUT == CSTR_STDOUT {
tee := io.MultiWriter(os.Stdout, bufout)
teeerr := io.MultiWriter(os.Stderr, errout)
c.Stdout = tee
c.Stderr = teeerr
setOut = true
}
} else if optS, ok := opt.(string); ok {
// Str(optS).Println("mode:")
if mode&CSTR_EXPECT == CSTR_EXPECT {
expectStr = optS
mode = mode ^ CSTR_EXPECT
} else if mode&CSTR_TYPE == CSTR_TYPE {
if expectStr != "" {
expects[Str(expectStr)] = Str(optS)
expectStr = ""
} else {
fmt.Println("simple")
c.Stdin = bytes.NewBuffer([]byte(optS))
}
mode = mode ^ CSTR_EXPECT
}
}
}
if !setOut {
tee := io.MultiWriter(bufout)
teeerr := io.MultiWriter(errout)
c.Stdout = tee
c.Stderr = teeerr
}
if len(expects) > 0 {
// tmpout := bytes.NewBuffer([]byte{})
// var tee io.Writer
// if mode&CSTR_STDOUT == CSTR_STDOUT {
tee := io.MultiWriter(os.Stdout, bufout)
// } else {
// tee = io.MultiWriter(tmpout, bufout)
// }
// c.Stdout = tee
c.Stdin = stdInput
tmpout, err := c.StdoutPipe()
if err != nil {
log.Fatal(err)
}
// lock.Add(1)
go func(expects Dict[Str, Str], closed *bool) {
// hit := 0
// tmpreader := bufio.NewReader(tmpout)
LOOP:
for {
// if tmpout.Len() > 0 {
linebuf := make([]byte, 1024)
// if tmpout.Len() > 0 {
n, err := tmpout.Read(linebuf)
if err != nil {
break LOOP
}
c := Str(linebuf[:n])
tee.Write(linebuf[:n])
// Str(c).Println("one:", expStr)
for _, line := range c.Split("\n") {
expects.Each(func(k, v Str) {
if line.ReMatch(k.String()) {
// k.ANSIUnderline().ANSIGreen().Println(line, " test ok type:", []byte(v))
stdInput.Write([]byte(v))
tee.Write([]byte(v))
// hit += 1
}
// } else {
// k.ANSISelected().ANSIUnderline().Println(line, "test failed:")
// }
})
}
}
stdInput.Close()
// fmt.Println("finished")
}(expects, &Closed)
}
// Str(input[0]).Print()
} else {
c.Stdout = bufout
c.Stderr = errout
// err = c.Run()
// var proc *os.Process
// proc, err = os.StartProcess(e[0], e[1:], &os.ProcAttr{
// Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
// })
// fmt.Println(proc.Pid)
}
// Str("wait ?").Println()
err = c.Run()
// tmpout.Close()
// lock.Wait()
Closed = true
// tmpout.Close()
if err != nil {
// log.Fatal("err cmd:", err)
cstr.history = cstr.history.Push(Str(cmd))
mmm, err := AutoEncodeToUTF8(errout.Bytes())
if err != nil {
fmt.Println("err:", err)
SafePush(&ErrStack, err)
}
cstr.outhistory = cstr.outhistory.Push(Str(mmm))
} else {
cstr.history = cstr.history.Push(Str(cmd))
mmm, err := AutoEncodeToUTF8(bufout.Bytes())
if err != nil {
log.Fatal(err, mmm)
SafePush(&ErrStack, err)
}
if errout.Len() > 0 {
mmm, err := AutoEncodeToUTF8(errout.Bytes())
if err != nil {
fmt.Println("err:", err)
SafePush(&ErrStack, err)
}
cstr.outhistory = cstr.outhistory.Push(Str(mmm))
}
cstr.outhistory = cstr.outhistory.Push(Str(mmm))
}
// Str("wait ok").Println()
return cstr
}
func (cstr CStr) Outputs() List[Str] {
return cstr.outhistory
}
func (cstr CStr) Histories() List[Str] {
return cstr.history
}
func (cstr CStr) Output(ix ...int) Str {
i := cstr.outhistory.Len() - 1
if ix != nil {
i = ix[0]
}
if i < 0 {
i = i + cstr.outhistory.Len()
}
return cstr.outhistory[i]
}
func (cstr CStr) History(ix ...int) Str {
i := cstr.history.Len() - 1
if ix != nil {
i = ix[0]
}
if i < 0 {
i = i + cstr.history.Len()
}
return cstr.history[i]
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。