mirror of
https://github.com/scroll-tech/scroll.git
synced 2026-01-13 16:08:04 -05:00
107 lines
2.0 KiB
Go
107 lines
2.0 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
"sync/atomic"
|
|
|
|
"github.com/docker/docker/pkg/reexec"
|
|
cmap "github.com/orcaman/concurrent-map"
|
|
)
|
|
|
|
var verbose bool
|
|
|
|
func init() {
|
|
v := os.Getenv("LOG_DOCKER")
|
|
if strings.ToLower(v) == "true" {
|
|
verbose = true
|
|
}
|
|
}
|
|
|
|
type checkFunc func(buf string)
|
|
|
|
// Cmd struct
|
|
type Cmd struct {
|
|
name string
|
|
args []string
|
|
|
|
isRunning uint64
|
|
cmd *exec.Cmd
|
|
app *exec.Cmd
|
|
|
|
checkFuncs cmap.ConcurrentMap //map[string]checkFunc
|
|
|
|
// open log flag.
|
|
openLog bool
|
|
// error channel
|
|
ErrChan chan error
|
|
}
|
|
|
|
// NewCmd create Cmd instance.
|
|
func NewCmd(name string, params ...string) *Cmd {
|
|
cmd := &Cmd{
|
|
checkFuncs: cmap.New(),
|
|
name: name,
|
|
args: params,
|
|
ErrChan: make(chan error, 10),
|
|
cmd: exec.Command(name, params...),
|
|
app: &exec.Cmd{
|
|
Path: reexec.Self(),
|
|
Args: append([]string{name}, params...),
|
|
},
|
|
}
|
|
cmd.cmd.Stdout = cmd
|
|
cmd.cmd.Stderr = cmd
|
|
cmd.app.Stdout = cmd
|
|
cmd.app.Stderr = cmd
|
|
return cmd
|
|
}
|
|
|
|
// RegistFunc register check func
|
|
func (c *Cmd) RegistFunc(key string, check checkFunc) {
|
|
c.checkFuncs.Set(key, check)
|
|
}
|
|
|
|
// UnRegistFunc unregister check func
|
|
func (c *Cmd) UnRegistFunc(key string) {
|
|
c.checkFuncs.Pop(key)
|
|
}
|
|
|
|
func (c *Cmd) runCmd() {
|
|
fmt.Println("cmd:", append([]string{c.name}, c.args...))
|
|
if atomic.CompareAndSwapUint64(&c.isRunning, 0, 1) {
|
|
c.ErrChan <- c.cmd.Run()
|
|
}
|
|
}
|
|
|
|
// RunCmd parallel running when parallel is true.
|
|
func (c *Cmd) RunCmd(parallel bool) {
|
|
if parallel {
|
|
go c.runCmd()
|
|
} else {
|
|
c.runCmd()
|
|
}
|
|
}
|
|
|
|
// OpenLog open cmd log by this api.
|
|
func (c *Cmd) OpenLog(open bool) {
|
|
c.openLog = open
|
|
}
|
|
|
|
func (c *Cmd) Write(data []byte) (int, error) {
|
|
out := string(data)
|
|
if verbose || c.openLog {
|
|
fmt.Printf("%s:\n\t%v", c.name, out)
|
|
} else if strings.Contains(strings.ToLower(out), "error") ||
|
|
strings.Contains(strings.ToLower(out), "warning") {
|
|
fmt.Printf("%s:\n\t%v", c.name, out)
|
|
}
|
|
go c.checkFuncs.IterCb(func(_ string, value interface{}) {
|
|
check := value.(checkFunc)
|
|
check(out)
|
|
})
|
|
return len(data), nil
|
|
}
|