Files
scroll/common/cmd/cmd.go
2023-08-31 20:15:26 +08:00

108 lines
2.1 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 v == "true" || 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") ||
strings.Contains(strings.ToLower(out), "info") {
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
}