增加 1.0版本
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
.idea/*
|
||||||
|
fileboy
|
||||||
|
fileboy.exe
|
||||||
|
filegirl.yaml
|
8
build-darwin.bat
Normal file
8
build-darwin.bat
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
@echo off
|
||||||
|
echo build start...
|
||||||
|
SET CGO_ENABLED=0
|
||||||
|
SET GOOS=darwin
|
||||||
|
SET GOARCH=amd64
|
||||||
|
go build -ldflags "-s -w"
|
||||||
|
echo build success
|
||||||
|
pause
|
8
build-linux.bat
Normal file
8
build-linux.bat
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
@echo off
|
||||||
|
echo build start...
|
||||||
|
SET CGO_ENABLED=0
|
||||||
|
SET GOOS=linux
|
||||||
|
SET GOARCH=amd64
|
||||||
|
go build -ldflags "-s -w"
|
||||||
|
echo build success
|
||||||
|
pause
|
8
build-windows.bat
Normal file
8
build-windows.bat
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
@echo off
|
||||||
|
echo build start...
|
||||||
|
SET CGO_ENABLED=0
|
||||||
|
SET GOOS=windows
|
||||||
|
SET GOARCH=amd64
|
||||||
|
go build -ldflags "-s -w"
|
||||||
|
echo build success
|
||||||
|
pause
|
240
fileboy.go
Normal file
240
fileboy.go
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"gopkg.in/fsnotify/fsnotify.v1"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Version = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
projectFolder string = "."
|
||||||
|
|
||||||
|
cfg *FileGirl
|
||||||
|
|
||||||
|
watcher *fsnotify.Watcher
|
||||||
|
|
||||||
|
cmd *exec.Cmd
|
||||||
|
|
||||||
|
runLock sync.Mutex
|
||||||
|
)
|
||||||
|
|
||||||
|
type wDirState struct {
|
||||||
|
Name string
|
||||||
|
Recursive bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseConfig() {
|
||||||
|
cfg = new(FileGirl)
|
||||||
|
fc, err := ioutil.ReadFile(projectFolder + "/filegirl.yaml")
|
||||||
|
if err != nil {
|
||||||
|
log.Panicln("read filegirl.yaml file err: ", err)
|
||||||
|
}
|
||||||
|
err = yaml.Unmarshal(fc, cfg)
|
||||||
|
if err != nil {
|
||||||
|
log.Panicln("parsed filegirl.yaml failed: ", err)
|
||||||
|
}
|
||||||
|
if cfg.Core.Version > Version {
|
||||||
|
log.Panicln("current fileboy support max version : ", Version)
|
||||||
|
}
|
||||||
|
log.Println(cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func eventDispatcher(event fsnotify.Event) {
|
||||||
|
ext := path.Ext(event.Name)
|
||||||
|
if len(cfg.Monitor.Types) > 0 &&
|
||||||
|
cfg.Monitor.Types[0] != ".*" &&
|
||||||
|
!inStringArray(ext, cfg.Monitor.Types) {
|
||||||
|
//log.Println(ext, cfg.Monitor.Types, inStringArray(ext, cfg.Monitor.Types))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch event.Op {
|
||||||
|
case fsnotify.Create:
|
||||||
|
case fsnotify.Write:
|
||||||
|
log.Println("event write : ", event.Name)
|
||||||
|
if cmd != nil {
|
||||||
|
err := cmd.Process.Kill()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("err: ", err)
|
||||||
|
}
|
||||||
|
log.Println("stop old process ")
|
||||||
|
}
|
||||||
|
go run()
|
||||||
|
case fsnotify.Remove:
|
||||||
|
case fsnotify.Rename:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func run() {
|
||||||
|
runLock.Lock()
|
||||||
|
defer runLock.Unlock()
|
||||||
|
for i := 0; i < len(cfg.Command.Exec); i++ {
|
||||||
|
carr := cmdParse2Array(cfg.Command.Exec[i])
|
||||||
|
cmd = exec.Command(carr[0], carr[1:]...)
|
||||||
|
//cmd.SysProcAttr = &syscall.SysProcAttr{CreationFlags: syscall.CREATE_UNICODE_ENVIRONMENT}
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
//cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
stdout, err := cmd.StdoutPipe()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error=>", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cmd.Start()
|
||||||
|
reader := bufio.NewReader(stdout)
|
||||||
|
for {
|
||||||
|
line, err2 := reader.ReadString('\n')
|
||||||
|
if err2 != nil || io.EOF == err2 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
log.Print(line)
|
||||||
|
}
|
||||||
|
err = cmd.Wait()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("cmd wait err ", err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
err = cmd.Process.Kill()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("cmd cannot kill ", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("end ")
|
||||||
|
}
|
||||||
|
|
||||||
|
func addWatcher() {
|
||||||
|
dirs := make([]string, 0)
|
||||||
|
for i := 0; i < len(cfg.Monitor.IncludeDirs); i++ {
|
||||||
|
darr := dirParse2Array(cfg.Monitor.IncludeDirs[i])
|
||||||
|
if len(darr) < 1 || len(darr) > 2 {
|
||||||
|
log.Fatalln("filegirl section monitor dirs is error. ", cfg.Monitor.IncludeDirs[i])
|
||||||
|
}
|
||||||
|
if darr[0] == "." {
|
||||||
|
if len(darr) == 2 && darr[1] == "*" {
|
||||||
|
dirs = make([]string, 0)
|
||||||
|
dirs = append(dirs, ".")
|
||||||
|
listFile(projectFolder, func(d string) {
|
||||||
|
dirs = arrayUniqueAdd(dirs, d)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
dirs = arrayUniqueAdd(dirs, projectFolder)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
if len(darr) == 2 && darr[1] == "*" {
|
||||||
|
listFile(projectFolder+"/"+darr[0], func(d string) {
|
||||||
|
dirs = arrayUniqueAdd(dirs, d)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
dirs = arrayUniqueAdd(dirs, projectFolder+"/"+darr[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
for i := 0; i < len(cfg.Monitor.ExceptDirs); i++ {
|
||||||
|
p := projectFolder + "/" + cfg.Monitor.ExceptDirs[i]
|
||||||
|
dirs = arrayRemoveElement(dirs, p)
|
||||||
|
listFile(p, func(d string) {
|
||||||
|
dirs = arrayRemoveElement(dirs, d)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
for _, dir := range dirs {
|
||||||
|
log.Println("watcher add -> ", dir)
|
||||||
|
err := watcher.Add(dir)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Println("fileboy is ready.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func initWatcher() {
|
||||||
|
parseConfig()
|
||||||
|
var err error
|
||||||
|
watcher, err = fsnotify.NewWatcher()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
defer watcher.Close()
|
||||||
|
|
||||||
|
done := make(chan bool)
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case event, ok := <-watcher.Events:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
eventDispatcher(event)
|
||||||
|
case err, ok := <-watcher.Errors:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println("error:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
addWatcher()
|
||||||
|
<-done
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseArgs() {
|
||||||
|
l := len(os.Args)
|
||||||
|
if l == 1 {
|
||||||
|
initWatcher()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if l == 2 {
|
||||||
|
c := os.Args[1]
|
||||||
|
switch c {
|
||||||
|
case "init":
|
||||||
|
err := ioutil.WriteFile(projectFolder+"/filegirl.yaml", []byte(exampleFileGirl), 0644)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error create filegirl.yaml config! ", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println("create filegirl.yaml ok")
|
||||||
|
return
|
||||||
|
case "exec":
|
||||||
|
parseConfig()
|
||||||
|
run()
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
fmt.Print(helpStr)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func show() {
|
||||||
|
fmt.Print(logo)
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
fmt.Println(englishSay[rand.Intn(len(englishSay))], "\r\n")
|
||||||
|
fmt.Println("Version: ", Version, " Author: deng@yoytang.com")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
log.SetPrefix("[FileBoy]: ")
|
||||||
|
log.SetFlags(2)
|
||||||
|
show()
|
||||||
|
var err error
|
||||||
|
projectFolder, err = os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
parseArgs()
|
||||||
|
}
|
17
filegirl.go
Normal file
17
filegirl.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type FileGirl struct {
|
||||||
|
Core struct {
|
||||||
|
Version int `yaml:"version"`
|
||||||
|
}
|
||||||
|
Monitor struct {
|
||||||
|
Types []string `yaml:"types"`
|
||||||
|
IncludeDirs []string `yaml:"includeDirs"`
|
||||||
|
ExceptDirs []string `yaml:"exceptDirs"`
|
||||||
|
}
|
||||||
|
Command struct {
|
||||||
|
//BeforeExec string `yaml:"beforeExec"`
|
||||||
|
Exec []string `yaml:"exec"`
|
||||||
|
//AfterExec string `yaml:"afterExec"`
|
||||||
|
}
|
||||||
|
}
|
72
raw.go
Normal file
72
raw.go
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
var exampleFileGirl string = `# 主配置
|
||||||
|
core:
|
||||||
|
# 配置版本号
|
||||||
|
version: 1
|
||||||
|
|
||||||
|
# 监控配置
|
||||||
|
monitor:
|
||||||
|
# 要监听的目录
|
||||||
|
# test1 监听当前目录下 test1 目录
|
||||||
|
# test1/test2 监听当前目录下 test1/test2 目录
|
||||||
|
# test1,* 监听当前目录下 test1 目录及其所有子目录(递归)
|
||||||
|
# .,* 监听当前目录及其所有子目录(递归)
|
||||||
|
includeDirs:
|
||||||
|
- .,*
|
||||||
|
|
||||||
|
# 不监听的目录
|
||||||
|
# .idea 忽略.idea目录及其所有子目录的监听
|
||||||
|
exceptDirs:
|
||||||
|
- .idea
|
||||||
|
- .git
|
||||||
|
- .vscode
|
||||||
|
|
||||||
|
# 监听文件的格式,此类文件更改会执行 commend 中的命令
|
||||||
|
# .go 后缀为 .go 的文件更改,会执行 commend 中的命令
|
||||||
|
# .* 所有的文件更改都会执行 commend 中的命令
|
||||||
|
types:
|
||||||
|
- .go
|
||||||
|
|
||||||
|
# 命令
|
||||||
|
command:
|
||||||
|
# 监听的文件有更改会执行的命令
|
||||||
|
# 可以有多条命令,会依次执行
|
||||||
|
# 如有多条命令,每条命令都会等待上一条命令执行完毕后才会执行
|
||||||
|
# 如遇交互式命令,允许外部获取输入
|
||||||
|
exec:
|
||||||
|
- go version
|
||||||
|
- go env
|
||||||
|
`
|
||||||
|
|
||||||
|
var helpStr = `fileboy [option]
|
||||||
|
Usage of fileboy:
|
||||||
|
无参数
|
||||||
|
读取当前目录下的 filegirl.yaml 配置,开始监听并工作
|
||||||
|
init
|
||||||
|
初始化 fileboy, 在当前目录生成 filegirl.yaml 配置文件
|
||||||
|
exec
|
||||||
|
尝试运行定义的 commend 命令
|
||||||
|
`
|
||||||
|
|
||||||
|
var englishSay = []string{
|
||||||
|
` Have you, the darkness is no darkness.`,
|
||||||
|
` Why do the good girls always love bad boys?`,
|
||||||
|
` If love is not madness.`,
|
||||||
|
` This world is so lonely without you.`,
|
||||||
|
` You lie. Silence in front of me.`,
|
||||||
|
` I need him like I need the air to breathe.`,
|
||||||
|
` Happiness is when the desolated soul meets love.`,
|
||||||
|
` What I can lose, but do not want to lose you.`,
|
||||||
|
` The same words, both miss, is also missed.`,
|
||||||
|
` Each bathed in the love of the people is a poet.`,
|
||||||
|
}
|
||||||
|
|
||||||
|
var logo = `
|
||||||
|
_______ _____ _ _______ ______ _____ _ _
|
||||||
|
(_______|_____) | (_______|____ \ / ___ \| | | |
|
||||||
|
_____ _ | | _____ ____) ) | | | |___| |
|
||||||
|
| ___) | | | | | ___) | __ (| | | |\_____/
|
||||||
|
| | _| |_| |_____| |_____| |__) ) |___| | ___
|
||||||
|
|_| (_____)_______)_______)______/ \_____/ (___)
|
||||||
|
`
|
66
util.go
Normal file
66
util.go
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func inStringArray(value string, arr []string) bool {
|
||||||
|
for _, v := range arr {
|
||||||
|
if value == v {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdParse2Array(s string) []string {
|
||||||
|
a := strings.Split(s, " ")
|
||||||
|
r := make([]string, 0)
|
||||||
|
for i := 0; i < len(a); i++ {
|
||||||
|
if ss := strings.Trim(a[i], " "); ss != "" {
|
||||||
|
r = append(r, ss)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func dirParse2Array(s string) []string {
|
||||||
|
a := strings.Split(s, ",")
|
||||||
|
r := make([]string, 0)
|
||||||
|
for i := 0; i < len(a); i++ {
|
||||||
|
if ss := strings.Trim(a[i], " "); ss != "" {
|
||||||
|
r = append(r, ss)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func listFile(folder string, fun func(string)) {
|
||||||
|
files, _ := ioutil.ReadDir(folder)
|
||||||
|
for _, file := range files {
|
||||||
|
if file.IsDir() {
|
||||||
|
d := folder + "/" + file.Name()
|
||||||
|
fun(d)
|
||||||
|
listFile(d, fun)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func arrayUniqueAdd(a []string, add string) []string {
|
||||||
|
if inStringArray(add, a) {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return append(a, add)
|
||||||
|
}
|
||||||
|
|
||||||
|
func arrayRemoveElement(a []string, r string) []string {
|
||||||
|
i := 0
|
||||||
|
for k, v := range a {
|
||||||
|
if v == r {
|
||||||
|
i = k
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return append(a[:i], a[i+1:]...)
|
||||||
|
}
|
Reference in New Issue
Block a user