3 Star 4 Fork 0

workits / pkgs

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
crun.go 3.69 KB
一键复制 编辑 原始数据 按行查看 历史
workits 提交于 2023-10-13 18:54 . 整合wk命令行工具
package toolx
import (
"fmt"
"os"
"os/exec"
"os/signal"
"regexp"
"sort"
"syscall"
"time"
"github.com/howeyc/fsnotify"
"github.com/mitchellh/go-ps"
)
var (
cmd *exec.Cmd
listenedDirs = make(map[string]any)
// 不需要监听的目录和文件
ignoreDirsReg = []string{
`(.+)\` + PS + `logs$`, // 日志目录
`(.+)\` + PS + `\.(.+)`, // 隐藏目录
}
ignoreFilesReg = []string{
`(.+).tmp$`,
`^\.(.+)`,
`(.+)~$`,
`(.+).log$`,
}
)
func Run() {
// 添加监听
watcher, err := fsnotify.NewWatcher()
if err != nil {
panic(err)
}
// 开启协程监听变化
go func() {
isReruning := false
for {
select {
case e := <-watcher.Event:
if cmd == nil || cmd.Process == nil || cmd.Process.Pid <= 0 {
continue
}
if isReruning {
continue
}
if isIgnoreFile(e.Name) {
continue
}
if e.IsCreate() || e.IsDelete() || e.IsModify() || e.IsRename() {
isReruning = true
go func() {
kill(cmd.Process.Pid)
time.Sleep(time.Second) // 等待1s
fmt.Println() // 空一行
addWatchDirs(watcher, ".")
isReruning = false
run()
}()
}
case err := <-watcher.Error:
panic(err)
}
}
}()
addWatchDirs(watcher, ".") // 添加监听目录
fmt.Println() // 添加一个空行
run() // 运行
// 阻塞进程 接收到
exit := make(chan os.Signal, 1)
signal.Notify(exit, syscall.SIGINT, syscall.SIGTERM)
<-exit
}
// 运行
func run() {
cmd = exec.Command("go", "run", ".")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
// 整理代码
prevCmd := exec.Command("go", "mod", "tidy")
prevCmd.Stdout = os.Stdout
prevCmd.Stderr = os.Stderr
if err := prevCmd.Run(); err != nil {
panic(err)
}
go func() {
_ = cmd.Run()
}()
}
// 杀死进程
func kill(pid int) {
pids := allProcesses(pid)
for _, id := range pids {
ps, err := os.FindProcess(id)
if err != nil {
panic(err)
}
err = ps.Kill()
if err != nil {
// 失败后2s后重试
time.AfterFunc(2*time.Second, func() {
_ = ps.Kill()
})
}
}
if err := cmd.Process.Kill(); err != nil {
panic(err)
}
}
// 根据pid查询所有子进程id
func allProcesses(pid int) []int {
pss, err := ps.Processes()
if err != nil {
panic(err)
}
// 对进程进行排序
sort.Slice(pss, func(i, j int) bool {
ppidLess := pss[i].PPid() < pss[j].PPid()
pidLess := pss[i].PPid() == pss[j].PPid() && pss[i].Pid() < pss[j].Pid()
return ppidLess || pidLess
})
// 查找所有子进程
pidPool := map[int]any{pid: nil}
for _, p := range pss {
ppid := p.PPid()
if _, exists := pidPool[ppid]; exists {
pidPool[p.Pid()] = nil
}
}
// 构造返回
rets := make([]int, 0)
for id := range pidPool {
rets = append(rets, id)
}
return rets
}
// 判断是否是被忽略的文件
func isIgnoreFile(fName string) bool {
for _, ignoreFileReg := range ignoreFilesReg {
if match, err := regexp.Match(ignoreFileReg, []byte(fName)); err == nil && match {
return true
}
}
return false
}
// 添加监听目录
func addWatchDirs(watcher *fsnotify.Watcher, pDir string) {
// 如果是忽略的目录跳过
for _, ignoreDirReg := range ignoreDirsReg {
if match, err := regexp.Match(ignoreDirReg, []byte(pDir)); err == nil && match {
return
}
}
// 添加监听目录
if _, has := listenedDirs[pDir]; !has {
if err := watcher.Watch(pDir); err != nil {
panic(err)
}
listenedDirs[pDir] = nil
fmt.Printf("监听目录: %s\n", pDir)
}
// 递归添加子目录
p, err := os.Open(pDir)
if err != nil {
panic(err)
}
fis, err := p.ReadDir(0)
if err != nil {
panic(err)
}
for _, fi := range fis {
if fi.IsDir() {
addWatchDirs(watcher, pDir+PS+fi.Name())
}
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/workits/pkgs.git
git@gitee.com:workits/pkgs.git
workits
pkgs
pkgs
v0.0.3

搜索帮助

344bd9b3 5694891 D2dac590 5694891