21 Commits

Author SHA1 Message Date
dengsgo
585f6e4389 增加 Copyright 2020-12-03 21:21:35 +08:00
dengsgo
600275f4a4 增加 changelog 2020-12-03 21:14:36 +08:00
dengsgo
a31bf71c1c 修改 进程退出清理日志 2020-12-03 21:11:00 +08:00
dengsgo
da54305188 增加 1.16 2020-10-17 10:29:33 +08:00
dengsgo
9e651d3023 优化 代码 2020-10-17 10:24:37 +08:00
dengsgo
605914d1e1 增加 1.16 2020-08-23 16:22:08 +08:00
dengsgo
86cf40564b 优化 文件扫描性能 2020-08-23 16:17:18 +08:00
dengsgo
819297118c 更新 changelog 2020-07-19 18:10:34 +08:00
dengsgo
a76d4cfe6c 增加 对信号的处理 2020-07-19 18:06:24 +08:00
dengsgo
14ba79c2b3 更新 README 2020-06-27 15:15:29 +08:00
dengsgo
c5f0649ab5 增加 pid文件进程感知 2020-06-27 15:11:55 +08:00
dengsgo
7c6f8f910b 增加 snap config 2020-04-22 15:40:09 +08:00
dengsgo
d07616bde9 rename 2020-03-16 11:19:13 +08:00
dengsgo
4f81692954 typo deamon->daemon 2020-03-16 11:16:14 +08:00
Deng.Liu
588af5143f Update README.md 2020-03-15 21:10:11 +08:00
Deng.Liu
2d8924b7fe Update go.yml 2020-03-15 21:02:32 +08:00
Deng.Liu
08fb7aabf8 Update go.yml 2020-03-15 20:56:56 +08:00
Deng.Liu
9f0a51ce0e Update go.yml 2020-03-15 20:55:31 +08:00
Deng.Liu
8a3a2d570b Update go.yml 2020-03-15 20:53:42 +08:00
Deng.Liu
e5405f4fa9 Update go.yml 2020-03-15 20:46:58 +08:00
Deng.Liu
9d9cce0f31 Create go.yml 2020-03-15 20:43:56 +08:00
16 changed files with 181 additions and 50 deletions

45
.github/workflows/go.yml vendored Normal file
View File

@@ -0,0 +1,45 @@
name: Go
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.13
uses: actions/setup-go@v1
with:
go-version: 1.13
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Get dependencies
run: |
export GO111MODULE=on
go env -w GOPROXY=https://goproxy.io,direct
go get
- name: Build
run: go build
- name: Use
run: |
export PATH=/home/runner/work/fileboy/fileboy:$PATH
fileboy version
fileboy help
fileboy init
cat filegirl.yaml
fileboy exec
fileboy daemon
ls -al .fileboy.pid
ps aux | grep fileboy
fileboy stop

View File

@@ -20,7 +20,7 @@ script:
- fileboy init
- cat filegirl.yaml
- fileboy exec
- fileboy deamon
- fileboy daemon
- ls -al .fileboy.pid
- ps aux | grep fileboy
- fileboy stop

View File

@@ -1,3 +1,23 @@
### Release v1.16
2020.12.03
- 修改 进程退出清理日志级别
- 增加 MIT Copyright
2020.08.23
- 优化 文件扫描性能
2020.07.19
- 增加 pid 文件处理
- 增加 信息处理
2020.03.16
- typo deamon->daemon
### Release v1.15
2020.03.08

View File

@@ -1,10 +1,10 @@
## 项目说明
[![Build Status](https://travis-ci.org/dengsgo/fileboy.svg?branch=master)](https://travis-ci.org/dengsgo/fileboy) [![Go Report Card](https://goreportcard.com/badge/github.com/dengsgo/fileboy)](https://goreportcard.com/report/github.com/dengsgo/fileboy)
![Go](https://github.com/dengsgo/fileboy/workflows/Go/badge.svg?branch=master) [![Build Status](https://travis-ci.org/dengsgo/fileboy.svg?branch=master)](https://travis-ci.org/dengsgo/fileboy) [![Go Report Card](https://goreportcard.com/badge/github.com/dengsgo/fileboy)](https://goreportcard.com/report/github.com/dengsgo/fileboy)
[简体中文](README.md) | [ENGLISH](README_EN.md)
fileboy文件变更监听通知系统,使用 Go 编写。
fileboy文件变更监听通知工具,使用 Go 编写。
适用于 Hot Reload 典型的如开发go项目无需每次手动执行 go build又比如前端 node 打包) 或者 系统监控的场景。
## 特性
@@ -140,7 +140,7 @@ notifier:
# 请求超时 15 秒
# POST 格式:
# Content-Type: application/json;charset=UTF-8
# User-Agent: FileBoy Net Notifier v1.15
# User-Agent: FileBoy Net Notifier v1.16
# Body: {"project_folder":"/project/path","file":"main.go","changed":1576567861913824940,"ext":".go","event":"write"}
# 例: http://example.com/notifier/fileboy-listener
# 不启用通知,请留空 ""

View File

@@ -4,7 +4,7 @@
[简体中文](README.md) | [ENGLISH](README_EN.md)
Fileboy, File Change Monitoring Notification System, written with Go.
Fileboy, File Change Monitoring Notification Tool Software, written with Go.
For Hot Reload scenarios (typically for developing go projects without having to perform go build manually every time; for example, front-end node packaging) or system monitoring.
## FEATURES
@@ -134,7 +134,7 @@ notifier:
# timeout 15 second
# POST :
# Content-Type: application/json;charset=UTF-8
# User-Agent: FileBoy Net Notifier v1.15
# User-Agent: FileBoy Net Notifier v1.16
# Body: {"project_folder":"/project/path","file":"main.go","changed":1576567861913824940,"ext":".go","event":"write"}
# e.g: http://example.com/notifier/fileboy-listener
# no notice is enabled. Please leave it blank. ""

View File

@@ -12,11 +12,11 @@ func getPidFile() string {
return projectFolder + "/.fileboy.pid"
}
func runAsDeamon() (int, error) {
func runAsDaemon() (int, error) {
if runtime.GOOS == "windows" {
logAndExit("daemons mode cannot run on windows.")
}
err := stopDeamon()
err := stopDaemon()
if err != nil {
logAndExit(err)
}
@@ -24,22 +24,22 @@ func runAsDeamon() (int, error) {
if err != nil {
logAndExit("cannot found `fileboy` command in the PATH")
}
deamon := exec.Command("fileboy")
deamon.Dir = projectFolder
deamon.Env = os.Environ()
deamon.Stdout = os.Stdout
err = deamon.Start()
daemon := exec.Command("fileboy")
daemon.Dir = projectFolder
daemon.Env = os.Environ()
daemon.Stdout = os.Stdout
err = daemon.Start()
if err != nil {
logAndExit(err)
}
pid := deamon.Process.Pid
pid := daemon.Process.Pid
if pid != 0 {
ioutil.WriteFile(getPidFile(), []byte(strconv.Itoa(pid)), 0644)
}
return pid, nil
}
func stopDeamon() error {
func stopDaemon() error {
bs, err := ioutil.ReadFile(getPidFile())
if err != nil {
return nil
@@ -48,3 +48,9 @@ func stopDeamon() error {
os.Remove(getPidFile())
return nil
}
func stopSelf() {
pid := os.Getpid()
os.Remove(getPidFile())
_ = exec.Command("kill", strconv.Itoa(pid)).Run()
}

View File

@@ -1,3 +1,7 @@
// Copyright (c) 2018-2020 Author dengsgo<dengsgo@yoytang.com> [https://github.com/dengsgo/fileboy]
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
package main
import (
@@ -6,9 +10,11 @@ import (
"log"
"math/rand"
"os"
"os/signal"
"path"
"strconv"
"strings"
"syscall"
"time"
"gopkg.in/fsnotify/fsnotify.v1"
@@ -111,6 +117,11 @@ func eventDispatcher(event fsnotify.Event) {
func addWatcher() {
logInfo("collecting directory information...")
dirsMap := map[string]bool{}
for _, dir := range cfg.Monitor.ExceptDirs {
if dir == "." {
logAndExit("exceptDirs must is not project root path ! err path:", dir)
}
}
for _, dir := range cfg.Monitor.IncludeDirs {
darr := dirParse2Array(dir)
if len(darr) < 1 || len(darr) > 2 {
@@ -145,16 +156,7 @@ func addWatcher() {
}
}
for _, dir := range cfg.Monitor.ExceptDirs {
if dir == "." {
logAndExit("exceptDirs must is not project root path ! err path:", dir)
}
p := projectFolder + "/" + dir
delete(dirsMap, p)
listFile(p, func(d string) {
delete(dirsMap, d)
})
}
for dir := range dirsMap {
logInfo("watcher add -> ", dir)
err := watcher.Add(dir)
@@ -200,6 +202,15 @@ func initWatcher() {
}
func watchChangeHandler(event fsnotify.Event) {
// stop the fileboy daemon process when the .fileboy.pid file is changed
if event.Name == getPidFile() &&
(event.Op == fsnotify.Remove ||
event.Op == fsnotify.Write ||
event.Op == fsnotify.Rename) {
logUInfo("exit daemon process")
stopSelf()
return
}
if event.Op != fsnotify.Create && event.Op != fsnotify.Rename {
return
}
@@ -213,13 +224,7 @@ func watchChangeHandler(event fsnotify.Event) {
continue
}
// check exceptDirs
has := false
for _, v := range cfg.Monitor.ExceptDirs {
if strings.HasPrefix(event.Name, projectFolder+"/"+v) {
has = true
}
}
if has {
if hitDirs(event.Name, &cfg.Monitor.ExceptDirs) {
continue
}
@@ -265,8 +270,8 @@ func parseArgs() {
case len(os.Args) > 1:
c := os.Args[1]
switch c {
case "deamon":
pid, err := runAsDeamon()
case "deamon", "daemon":
pid, err := runAsDaemon()
if err != nil {
logAndExit(err)
}
@@ -274,7 +279,7 @@ func parseArgs() {
logUInfo("fileboy is ready. the main process will run as a daemons")
return
case "stop":
err := stopDeamon()
err := stopDaemon()
if err != nil {
logAndExit(err)
}
@@ -310,6 +315,20 @@ func parseArgs() {
}
}
func signalHandler() {
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
if taskMan != nil && taskMan.cmd != nil && taskMan.cmd.Process != nil {
if err := taskMan.cmd.Process.Kill(); err != nil {
logWarn("stopping the process failed: PID:", taskMan.cmd.ProcessState.Pid(), ":", err)
}
}
os.Exit(0)
}()
}
func getFileGirlPath() string {
return projectFolder + "/" + filegirlYamlName
}
@@ -332,5 +351,6 @@ func main() {
if err != nil {
logAndExit(err)
}
signalHandler()
parseArgs()
}

View File

@@ -1,3 +1,7 @@
// Copyright (c) 2018-2020 Author dengsgo<dengsgo@yoytang.com> [https://github.com/dengsgo/fileboy]
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
package main
type FileGirl struct {

4
go.mod
View File

@@ -3,7 +3,7 @@ module fileboy
go 1.13
require (
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 // indirect
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 // indirect
gopkg.in/fsnotify/fsnotify.v1 v1.4.7
gopkg.in/yaml.v2 v2.2.8
gopkg.in/yaml.v2 v2.3.0
)

6
go.sum
View File

@@ -1,7 +1,13 @@
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200408040146-ea54a3c99b9b h1:h03Ur1RlPrGTjua4koYdpGl8W0eYo8p1uI9w7RPlkdk=
golang.org/x/sys v0.0.0-20200408040146-ea54a3c99b9b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88=
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify/fsnotify.v1 v1.4.7 h1:XNNYLJHt73EyYiCZi6+xjupS9CpvmiDgjPTAjrBlQbo=
gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@@ -1,3 +1,7 @@
// Copyright (c) 2018-2020 Author dengsgo<dengsgo@yoytang.com> [https://github.com/dengsgo/fileboy]
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
package main
import (
@@ -61,7 +65,7 @@ func (n *NetNotifier) dispatch(params *postParams) {
return
}
req.Header.Set("Content-Type", "application/json;charset=UTF-8")
req.Header.Set("User-Agent", "FileBoy Net Notifier v1.15")
req.Header.Set("User-Agent", "FileBoy Net Notifier v1.16")
resp, err := client.Do(req)
if err != nil {
logError("notifier call failed. err:", err)

10
raw.go
View File

@@ -76,7 +76,7 @@ notifier:
# 请求超时 15 秒
# POST 格式:
# Content-Type: application/json;charset=UTF-8
# User-Agent: FileBoy Net Notifier v1.15
# User-Agent: FileBoy Net Notifier v1.16
# Body: {"project_folder":"/project/path","file":"main.go","changed":1576567861913824940,"ext":".go","event":"write"}
# 例: http://example.com/notifier/fileboy-listener
# 不启用通知,请留空 ""
@@ -112,7 +112,7 @@ Usage of fileboy:
初始化 fileboy, 在当前目录生成 filegirl.yaml 配置文件
exec
尝试运行定义的 command 命令
deamon
daemon
读取当前目录下的 filegirl.yaml 配置,以守护进程的方式运行在后台
stop
停止守护进程
@@ -139,13 +139,13 @@ var logo = `
_____ _ | | _____ ____) ) | | | |___| |
| ___) | | | | | ___) | __ (| | | |\_____/
| | _| |_| |_____| |_____| |__) ) |___| | ___
|_| (_____)_______)_______)______/ \_____/ (___) V1.15
|_| (_____)_______)_______)______/ \_____/ (___) V1.16
`
var statement = `Dengsgo [dengsgo@gmail.com] Open Source with MIT License`
var versionDesc = `
Version fileboy: v1.15 filegirl: v` + strconv.Itoa(Version) + `
Released 2020.03.08
Version fileboy: v1.16 filegirl: v` + strconv.Itoa(Version) + `
Released 2020.10.17
Licence MIT
Author dengsgo [dengsgo@gmail.com]
Website https://github.com/dengsgo/fileboy

BIN
resources/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

8
snapcraft.yaml Normal file
View File

@@ -0,0 +1,8 @@
name: fileboy
vendor: dengsgo, https://github.com/dengsgo, <dengsgo@yoytang.com>
summary: File Change Monitoring Notification Tools.
description: File Change Monitoring Notification Tools. Please Visit https://github.com/dengsgo/fileboy
version: 1.15
icon: resources/icon.png
base: core18
grade: stable

View File

@@ -1,3 +1,7 @@
// Copyright (c) 2018-2020 Author dengsgo<dengsgo@yoytang.com> [https://github.com/dengsgo/fileboy]
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
package main
import (
@@ -30,14 +34,15 @@ func newTaskMan(delay int, callUrl string) *TaskMan {
go func() {
for {
<-t.waitChan
if len(t.waitQueue) > 0 {
cf := t.waitQueue[len(t.waitQueue)-1]
if len(t.waitQueue) > 1 {
logInfo("redundant tasks dropped:", len(t.waitQueue)-1)
}
t.waitQueue = []*changedFile{}
go t.preRun(cf)
if len(t.waitQueue) < 1 {
return
}
cf := t.waitQueue[len(t.waitQueue)-1]
if len(t.waitQueue) > 1 {
logInfo("redundant tasks dropped:", len(t.waitQueue)-1)
}
t.waitQueue = []*changedFile{}
go t.preRun(cf)
}
}()
}

13
util.go
View File

@@ -53,11 +53,24 @@ func dirParse2Array(s string) []string {
return r
}
func hitDirs(d string, dirs *[]string) bool {
d += "/"
for _, v := range *dirs {
if strings.HasPrefix(d, projectFolder+"/"+v+"/") {
return true
}
}
return false
}
func listFile(folder string, fun func(string)) {
files, _ := ioutil.ReadDir(folder)
for _, file := range files {
if file.IsDir() {
d := folder + "/" + file.Name()
if hitDirs(d, &cfg.Monitor.ExceptDirs) {
continue
}
fun(d)
listFile(d, fun)
}