基于fsnotify的文件监控模块,为eSync自动编译加载提供更改监听功能!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

309 lines
6.6 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. package main
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "io"
  6. "io/fs"
  7. "os"
  8. "path/filepath"
  9. "strings"
  10. "time"
  11. "github.com/fsnotify/fsnotify"
  12. )
  13. const (
  14. SendDur = 1111 // 发送时间间隔毫秒
  15. SleepDur = 86400000 // 定期器初始睡眠时间
  16. )
  17. var CollectFiles map[string]struct{}
  18. var CollectExt map[string]struct{}
  19. var SendTimer *time.Timer
  20. var Str bytes.Buffer
  21. var AddExtraDirs []string
  22. var AddOnlyDirs []string
  23. var OnlyDirs []string
  24. var DelDirs []string
  25. var LenBuff []byte
  26. type Watch struct {
  27. watch *fsnotify.Watcher
  28. }
  29. const (
  30. //LOGPATH LOGPATH/time.Now().Format(FORMAT)/*.log
  31. LOGPATH = "./"
  32. //FORMAT .
  33. FORMAT = "20060102"
  34. //LineFeed 换行
  35. LineFeed = "\r\n"
  36. FileName = "fileSync.log"
  37. )
  38. //以天为基准,存日志
  39. var path = LOGPATH + time.Now().Format(FORMAT) + "_"
  40. //WriteLog return error
  41. func WriteLog(msg string) error {
  42. var (
  43. err error
  44. f *os.File
  45. )
  46. f, err = os.OpenFile(path+FileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
  47. _, err = io.WriteString(f, "Tag"+"::"+msg+LineFeed)
  48. defer f.Close()
  49. return err
  50. }
  51. //IsExist 判断文件夹/文件是否存在 存在返回 true
  52. func IsExist(f string) bool {
  53. _, err := os.Stat(f)
  54. return err == nil || os.IsExist(err)
  55. }
  56. // 收集更改了的文件
  57. func CollectFile(File string) {
  58. ext := filepath.Ext(File)
  59. if _, ok := CollectExt[ext]; ok{
  60. CollectFiles[File] = struct{}{}
  61. SendTimer.Reset(time.Millisecond * SendDur)
  62. }
  63. }
  64. func isHidden(path string) bool {
  65. for i := len(path) - 1; i > 0; i-- {
  66. if path[i] != '.' {
  67. continue
  68. }
  69. if os.IsPathSeparator(path[i-1]) {
  70. return true
  71. }
  72. }
  73. if path[0] == '.' {
  74. return true
  75. }
  76. return false
  77. }
  78. func isOnlyDir(dirs []string, curDirs string) bool {
  79. cnt := 0
  80. for _, v := range dirs {
  81. if v != "" {
  82. cnt += 1
  83. if strings.Contains(curDirs[1:], v[1:]) {
  84. return true
  85. }
  86. }
  87. }
  88. if cnt == 0 {
  89. return true
  90. }
  91. return false
  92. }
  93. func isDelDir(dirs []string, curDirs string) bool {
  94. for _, v := range dirs {
  95. if v != "" {
  96. if strings.Contains(curDirs[1:], v[1:]) {
  97. return true
  98. }
  99. }
  100. }
  101. return false
  102. }
  103. // 判断所给路径文件/文件夹是否存在
  104. func existPath(path string) bool {
  105. _, err := os.Stat(path) //os.Stat获取文件信息
  106. if err != nil {
  107. if os.IsNotExist(err) {
  108. return false
  109. }
  110. return true
  111. }
  112. return true
  113. }
  114. //监控目录
  115. func (w *Watch) watchDir(dir string) {
  116. // 启动文件监听goroutine
  117. go func() {
  118. for {
  119. select {
  120. case ev := <-w.watch.Events:
  121. {
  122. if ev.Has(fsnotify.Create) {
  123. //这里获取新创建文件的信息,如果是目录,则加入监控中
  124. fi, err := os.Stat(ev.Name)
  125. if err == nil && fi.IsDir() {
  126. // 新建了文件夹
  127. if !isHidden(ev.Name) {
  128. if isOnlyDir(OnlyDirs, ev.Name) {
  129. if !isDelDir(DelDirs, ev.Name) {
  130. w.watch.Add(ev.Name)
  131. }
  132. }
  133. }
  134. } else {
  135. // 新建了文件
  136. CollectFile(ev.Name)
  137. }
  138. }
  139. if ev.Has(fsnotify.Write) {
  140. CollectFile(ev.Name)
  141. }
  142. if ev.Has(fsnotify.Remove) {
  143. //如果删除文件是目录,则移除监控
  144. fi, err := os.Stat(ev.Name)
  145. if err == nil && fi.IsDir() {
  146. w.watch.Remove(ev.Name)
  147. }
  148. }
  149. if ev.Has(fsnotify.Rename) {
  150. //如果重命名文件是目录,则移除监控
  151. //注意这里无法使用os.Stat来判断是否是目录了
  152. //因为重命名后,go已经无法找到原文件来获取信息了
  153. //所以这里就简单粗爆的直接remove好了
  154. w.watch.Remove(ev.Name)
  155. }
  156. if ev.Has(fsnotify.Chmod) {
  157. }
  158. }
  159. case <-w.watch.Errors:
  160. {
  161. continue
  162. }
  163. case <-SendTimer.C:
  164. SendToErl()
  165. }
  166. }
  167. }()
  168. //通过Walk来遍历目录下的所有子目录
  169. filepath.WalkDir(dir, func(path string, info fs.DirEntry, err error) error {
  170. //这里判断是否为目录,只需监控目录即可 目录下的文件也在监控范围内,不需要我们一个一个加
  171. if err == nil && info.IsDir() {
  172. path, err := filepath.Abs(path)
  173. if err != nil {
  174. return err
  175. }
  176. if !isHidden(path) && isOnlyDir(OnlyDirs, path) && !isDelDir(DelDirs, path) {
  177. err = w.watch.Add(path)
  178. if err != nil {
  179. return err
  180. }
  181. }
  182. }
  183. return nil
  184. })
  185. for _, v := range AddExtraDirs {
  186. if v != "" && existPath(v) {
  187. //通过Walk来遍历目录下的所有子目录
  188. filepath.WalkDir(v, func(path string, info fs.DirEntry, err error) error {
  189. //这里判断是否为目录,只需监控目录即可 目录下的文件也在监控范围内,不需要我们一个一个加
  190. if err == nil && info.IsDir() {
  191. path, err := filepath.Abs(path)
  192. if err != nil {
  193. return err
  194. }
  195. if !isHidden(path) {
  196. err = w.watch.Add(path)
  197. if err != nil {
  198. return err
  199. }
  200. }
  201. }
  202. return nil
  203. })
  204. }
  205. }
  206. for _, v := range AddOnlyDirs {
  207. if v != "" && existPath(v) {
  208. w.watch.Add(v)
  209. }
  210. }
  211. }
  212. //********************************************** port start ************************************************************
  213. func ReadLen() (int32, error) {
  214. if _, err := io.ReadFull(os.Stdin, LenBuff); err != nil {
  215. return 0, err
  216. }
  217. size := int32(binary.BigEndian.Uint32(LenBuff))
  218. return size, nil
  219. }
  220. func Read() ([]byte, error) {
  221. len, err := ReadLen()
  222. if err != nil {
  223. return nil, err
  224. } else if len == 0 {
  225. return []byte{}, nil
  226. }
  227. data := make([]byte, len)
  228. size, err := io.ReadFull(os.Stdin, data)
  229. return data[:size], err
  230. }
  231. func Write(data []byte) (int, error) {
  232. size := len(data)
  233. binary.BigEndian.PutUint32(LenBuff, uint32(size))
  234. if _, err := os.Stdout.Write(LenBuff); err != nil {
  235. return 0, err
  236. }
  237. return os.Stdout.Write(data)
  238. }
  239. // 发送文件列表到erl层
  240. func SendToErl() {
  241. for k := range CollectFiles {
  242. Str.WriteString(k)
  243. Str.WriteString("\r\n")
  244. }
  245. CollectFiles = map[string]struct{}{}
  246. Write(Str.Bytes())
  247. Str.Reset()
  248. }
  249. //********************************************** port end ************************************************************
  250. func main() {
  251. CollectFiles = map[string]struct{}{}
  252. CollectExt = map[string]struct{}{}
  253. LenBuff = make([]byte, 4)
  254. SendTimer = time.NewTimer(time.Millisecond * SleepDur)
  255. defer SendTimer.Stop()
  256. Write([]byte("init"))
  257. args := os.Args
  258. ExtList := strings.Split(args[2], "|")
  259. for _, v := range ExtList {
  260. CollectExt[v] = struct{}{}
  261. }
  262. dirs := strings.Split(args[3], "\r\n")
  263. AddExtraDirs = strings.Split(dirs[0], "|")
  264. AddOnlyDirs = strings.Split(dirs[1], "|")
  265. OnlyDirs = strings.Split(dirs[2], "|")
  266. DelDirs = strings.Split(dirs[3], "|")
  267. watch, _ := fsnotify.NewWatcher()
  268. defer watch.Close()
  269. w := Watch{watch: watch}
  270. w.watchDir(args[1])
  271. Read()
  272. }