refactor: extract path logic to path.go and run go fmt on codebase
This commit is contained in:
+15
-15
@@ -137,21 +137,21 @@ type TaskResult struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Agent struct {
|
type Agent struct {
|
||||||
config *Config
|
config *Config
|
||||||
configFile string
|
configFile string
|
||||||
machineID string
|
machineID string
|
||||||
scheduler *executor.Scheduler
|
scheduler *executor.Scheduler
|
||||||
cronManager *executor.CronManager
|
cronManager *executor.CronManager
|
||||||
tasks map[string]*AgentTask // 本地任务缓存,用于执行 lookup
|
tasks map[string]*AgentTask // 本地任务缓存,用于执行 lookup
|
||||||
lastTaskCount int
|
lastTaskCount int
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
client *http.Client
|
client *http.Client
|
||||||
wsConn *websocket.Conn
|
wsConn *websocket.Conn
|
||||||
wsMu sync.Mutex
|
wsMu sync.Mutex
|
||||||
stopCh chan struct{}
|
stopCh chan struct{}
|
||||||
wsStopCh chan struct{} // 用于停止当前 WebSocket 相关的 goroutine
|
wsStopCh chan struct{} // 用于停止当前 WebSocket 相关的 goroutine
|
||||||
taskLogs map[string][]string // 记录最近的日志行,用于失败显示
|
taskLogs map[string][]string // 记录最近的日志行,用于失败显示
|
||||||
logMu sync.Mutex // taskLogs 的锁
|
logMu sync.Mutex // taskLogs 的锁
|
||||||
schedulerStarted bool // 调度器是否已经启动
|
schedulerStarted bool // 调度器是否已经启动
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,81 +1,6 @@
|
|||||||
package constant
|
package constant
|
||||||
|
|
||||||
import (
|
import "time"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ConfigPath 配置文件路径
|
|
||||||
ConfigPath string
|
|
||||||
|
|
||||||
// DataDir 数据目录
|
|
||||||
DataDir string
|
|
||||||
|
|
||||||
// DefaultDBPath 默认数据库路径
|
|
||||||
DefaultDBPath string
|
|
||||||
|
|
||||||
// WebDistDir 前端构建目录
|
|
||||||
WebDistDir string
|
|
||||||
|
|
||||||
// ScriptsWorkDir 脚本工作目录
|
|
||||||
ScriptsWorkDir string
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rootDir := ResolveAppRootDir()
|
|
||||||
ConfigPath = filepath.Clean(filepath.Join(rootDir, "configs", "config.ini"))
|
|
||||||
DataDir = filepath.Clean(filepath.Join(rootDir, "data"))
|
|
||||||
DefaultDBPath = filepath.Clean(filepath.Join(rootDir, "data", "baihu.db"))
|
|
||||||
WebDistDir = filepath.Clean(filepath.Join(rootDir, "web", "dist"))
|
|
||||||
ScriptsWorkDir = filepath.Clean(filepath.Join(rootDir, "data", "scripts"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResolveAppRootDir 获取应用程序的绝对根目录路径。
|
|
||||||
func ResolveAppRootDir() string {
|
|
||||||
// 1. 检查当前工作目录(CWD)及其上级目录
|
|
||||||
if cwd, err := os.Getwd(); err == nil {
|
|
||||||
dir := cwd
|
|
||||||
for {
|
|
||||||
if _, err := os.Stat(filepath.Join(dir, "configs", "config.ini")); err == nil {
|
|
||||||
return dir
|
|
||||||
}
|
|
||||||
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
|
|
||||||
return dir
|
|
||||||
}
|
|
||||||
parent := filepath.Dir(dir)
|
|
||||||
if parent == dir {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
dir = parent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 检查当前可执行文件路径及其上级目录
|
|
||||||
if exe, err := os.Executable(); err == nil {
|
|
||||||
dir := filepath.Dir(exe)
|
|
||||||
for {
|
|
||||||
if _, err := os.Stat(filepath.Join(dir, "configs", "config.ini")); err == nil {
|
|
||||||
return dir
|
|
||||||
}
|
|
||||||
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
|
|
||||||
return dir
|
|
||||||
}
|
|
||||||
parent := filepath.Dir(dir)
|
|
||||||
if parent == dir {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
dir = parent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 兜底回退到当前工作目录
|
|
||||||
if cwd, err := os.Getwd(); err == nil {
|
|
||||||
return cwd
|
|
||||||
}
|
|
||||||
return "."
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package constant
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ConfigPath 配置文件路径
|
||||||
|
ConfigPath string
|
||||||
|
|
||||||
|
// DataDir 数据目录
|
||||||
|
DataDir string
|
||||||
|
|
||||||
|
// DefaultDBPath 默认数据库路径
|
||||||
|
DefaultDBPath string
|
||||||
|
|
||||||
|
// WebDistDir 前端构建目录
|
||||||
|
WebDistDir string
|
||||||
|
|
||||||
|
// ScriptsWorkDir 脚本工作目录
|
||||||
|
ScriptsWorkDir string
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rootDir := ResolveAppRootDir()
|
||||||
|
ConfigPath = filepath.Clean(filepath.Join(rootDir, "configs", "config.ini"))
|
||||||
|
DataDir = filepath.Clean(filepath.Join(rootDir, "data"))
|
||||||
|
DefaultDBPath = filepath.Clean(filepath.Join(rootDir, "data", "baihu.db"))
|
||||||
|
WebDistDir = filepath.Clean(filepath.Join(rootDir, "web", "dist"))
|
||||||
|
ScriptsWorkDir = filepath.Clean(filepath.Join(rootDir, "data", "scripts"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResolveAppRootDir 获取应用程序的绝对根目录路径。
|
||||||
|
func ResolveAppRootDir() string {
|
||||||
|
// 1. 检查当前工作目录(CWD)及其上级目录
|
||||||
|
if cwd, err := os.Getwd(); err == nil {
|
||||||
|
dir := cwd
|
||||||
|
for {
|
||||||
|
if _, err := os.Stat(filepath.Join(dir, "configs", "config.ini")); err == nil {
|
||||||
|
return dir
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
|
||||||
|
return dir
|
||||||
|
}
|
||||||
|
parent := filepath.Dir(dir)
|
||||||
|
if parent == dir {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
dir = parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 检查当前可执行文件路径及其上级目录
|
||||||
|
if exe, err := os.Executable(); err == nil {
|
||||||
|
dir := filepath.Dir(exe)
|
||||||
|
for {
|
||||||
|
if _, err := os.Stat(filepath.Join(dir, "configs", "config.ini")); err == nil {
|
||||||
|
return dir
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
|
||||||
|
return dir
|
||||||
|
}
|
||||||
|
parent := filepath.Dir(dir)
|
||||||
|
if parent == dir {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
dir = parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 兜底回退到当前工作目录
|
||||||
|
if cwd, err := os.Getwd(); err == nil {
|
||||||
|
return cwd
|
||||||
|
}
|
||||||
|
return "."
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|||||||
@@ -42,11 +42,11 @@ func (ec *EnvController) CreateEnvVar(c *gin.Context) {
|
|||||||
userID := c.GetString("userID")
|
userID := c.GetString("userID")
|
||||||
|
|
||||||
var req struct {
|
var req struct {
|
||||||
Name string `json:"name" binding:"required"`
|
Name string `json:"name" binding:"required"`
|
||||||
Value string `json:"value" binding:"required"`
|
Value string `json:"value" binding:"required"`
|
||||||
Remark string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Hidden *bool `json:"hidden"`
|
Hidden *bool `json:"hidden"`
|
||||||
Enabled *bool `json:"enabled"`
|
Enabled *bool `json:"enabled"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
||||||
"github.com/engigu/baihu-panel/internal/database"
|
"github.com/engigu/baihu-panel/internal/database"
|
||||||
"github.com/engigu/baihu-panel/internal/models"
|
"github.com/engigu/baihu-panel/internal/models"
|
||||||
"github.com/engigu/baihu-panel/internal/models/vo"
|
"github.com/engigu/baihu-panel/internal/models/vo"
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ func (c *MiseController) VerifyCommand(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
utils.Success(ctx, gin.H{"command": cmd})
|
utils.Success(ctx, gin.H{"command": cmd})
|
||||||
}
|
}
|
||||||
|
|
||||||
// UseGlobal 设置全局默认版本
|
// UseGlobal 设置全局默认版本
|
||||||
func (c *MiseController) UseGlobal(ctx *gin.Context) {
|
func (c *MiseController) UseGlobal(ctx *gin.Context) {
|
||||||
var req struct {
|
var req struct {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
||||||
"github.com/engigu/baihu-panel/internal/models/vo"
|
"github.com/engigu/baihu-panel/internal/models/vo"
|
||||||
"github.com/engigu/baihu-panel/internal/services"
|
"github.com/engigu/baihu-panel/internal/services"
|
||||||
"github.com/engigu/baihu-panel/internal/utils"
|
"github.com/engigu/baihu-panel/internal/utils"
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/engigu/baihu-panel/internal/constant"
|
"github.com/engigu/baihu-panel/internal/constant"
|
||||||
|
"github.com/engigu/baihu-panel/internal/logger"
|
||||||
"github.com/engigu/baihu-panel/internal/models"
|
"github.com/engigu/baihu-panel/internal/models"
|
||||||
"github.com/engigu/baihu-panel/internal/models/vo"
|
"github.com/engigu/baihu-panel/internal/models/vo"
|
||||||
"github.com/engigu/baihu-panel/internal/services"
|
"github.com/engigu/baihu-panel/internal/services"
|
||||||
"github.com/engigu/baihu-panel/internal/services/tasks"
|
"github.com/engigu/baihu-panel/internal/services/tasks"
|
||||||
"github.com/engigu/baihu-panel/internal/utils"
|
"github.com/engigu/baihu-panel/internal/utils"
|
||||||
"github.com/engigu/baihu-panel/internal/logger"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"os"
|
"os"
|
||||||
@@ -59,26 +59,26 @@ func resolveWorkDir(workDir string) string {
|
|||||||
|
|
||||||
func (tc *TaskController) CreateTask(c *gin.Context) {
|
func (tc *TaskController) CreateTask(c *gin.Context) {
|
||||||
var req struct {
|
var req struct {
|
||||||
Name string `json:"name" binding:"required"`
|
Name string `json:"name" binding:"required"`
|
||||||
Remark string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
Command string `json:"command"`
|
Command string `json:"command"`
|
||||||
PreCommand string `json:"pre_command"`
|
PreCommand string `json:"pre_command"`
|
||||||
PostCommand string `json:"post_command"`
|
PostCommand string `json:"post_command"`
|
||||||
Tags string `json:"tags"`
|
Tags string `json:"tags"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Config string `json:"config"`
|
Config string `json:"config"`
|
||||||
Schedule string `json:"schedule"`
|
Schedule string `json:"schedule"`
|
||||||
Timeout int `json:"timeout"`
|
Timeout int `json:"timeout"`
|
||||||
WorkDir string `json:"work_dir"`
|
WorkDir string `json:"work_dir"`
|
||||||
CleanConfig string `json:"clean_config"`
|
CleanConfig string `json:"clean_config"`
|
||||||
Envs string `json:"envs"`
|
Envs string `json:"envs"`
|
||||||
Languages models.TaskLanguages `json:"languages"`
|
Languages models.TaskLanguages `json:"languages"`
|
||||||
AgentID *string `json:"agent_id"`
|
AgentID *string `json:"agent_id"`
|
||||||
TriggerType string `json:"trigger_type"`
|
TriggerType string `json:"trigger_type"`
|
||||||
RetryCount int `json:"retry_count"`
|
RetryCount int `json:"retry_count"`
|
||||||
RetryInterval int `json:"retry_interval"`
|
RetryInterval int `json:"retry_interval"`
|
||||||
RandomRange int `json:"random_range"`
|
RandomRange int `json:"random_range"`
|
||||||
PinType string `json:"pin_type"`
|
PinType string `json:"pin_type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
@@ -251,27 +251,27 @@ func (tc *TaskController) UpdateTask(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var req struct {
|
var req struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Remark string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
Command string `json:"command"`
|
Command string `json:"command"`
|
||||||
PreCommand string `json:"pre_command"`
|
PreCommand string `json:"pre_command"`
|
||||||
PostCommand string `json:"post_command"`
|
PostCommand string `json:"post_command"`
|
||||||
Tags string `json:"tags"`
|
Tags string `json:"tags"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Config string `json:"config"`
|
Config string `json:"config"`
|
||||||
Schedule string `json:"schedule"`
|
Schedule string `json:"schedule"`
|
||||||
Timeout int `json:"timeout"`
|
Timeout int `json:"timeout"`
|
||||||
WorkDir string `json:"work_dir"`
|
WorkDir string `json:"work_dir"`
|
||||||
CleanConfig string `json:"clean_config"`
|
CleanConfig string `json:"clean_config"`
|
||||||
Envs string `json:"envs"`
|
Envs string `json:"envs"`
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
Languages models.TaskLanguages `json:"languages"`
|
Languages models.TaskLanguages `json:"languages"`
|
||||||
AgentID *string `json:"agent_id"`
|
AgentID *string `json:"agent_id"`
|
||||||
TriggerType string `json:"trigger_type"`
|
TriggerType string `json:"trigger_type"`
|
||||||
RetryCount int `json:"retry_count"`
|
RetryCount int `json:"retry_count"`
|
||||||
RetryInterval int `json:"retry_interval"`
|
RetryInterval int `json:"retry_interval"`
|
||||||
RandomRange int `json:"random_range"`
|
RandomRange int `json:"random_range"`
|
||||||
PinType string `json:"pin_type"`
|
PinType string `json:"pin_type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
@@ -695,4 +695,3 @@ func (tc *TaskController) ToggleTask(c *gin.Context) {
|
|||||||
|
|
||||||
utils.Success(c, vo.ToTaskVO(updatedTask))
|
utils.Success(c, vo.ToTaskVO(updatedTask))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
"strings"
|
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/engigu/baihu-panel/internal/constant"
|
"github.com/engigu/baihu-panel/internal/constant"
|
||||||
@@ -23,7 +23,6 @@ import (
|
|||||||
"golang.org/x/text/transform"
|
"golang.org/x/text/transform"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
type TerminalController struct {
|
type TerminalController struct {
|
||||||
envService *services.EnvService
|
envService *services.EnvService
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,9 +64,9 @@ func Init(cfg *Config) error {
|
|||||||
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
|
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
|
||||||
gormlogger.Config{
|
gormlogger.Config{
|
||||||
SlowThreshold: time.Millisecond * 500, // 慢 SQL 阈值,默认是 200ms,这里改为 500ms
|
SlowThreshold: time.Millisecond * 500, // 慢 SQL 阈值,默认是 200ms,这里改为 500ms
|
||||||
LogLevel: gormlogger.Warn, // 日志级别
|
LogLevel: gormlogger.Warn, // 日志级别
|
||||||
IgnoreRecordNotFoundError: true, // 忽略 ErrRecordNotFound(找不到记录)错误
|
IgnoreRecordNotFoundError: true, // 忽略 ErrRecordNotFound(找不到记录)错误
|
||||||
Colorful: true, // 禁用彩色打印
|
Colorful: true, // 禁用彩色打印
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,6 @@ func getModelSignature(models []interface{}) string {
|
|||||||
return hex.EncodeToString(hash[:])
|
return hex.EncodeToString(hash[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// customMigrations 自定义迁移(处理 AutoMigrate 无法自动完成的变更)
|
// customMigrations 自定义迁移(处理 AutoMigrate 无法自动完成的变更)
|
||||||
func customMigrations() error {
|
func customMigrations() error {
|
||||||
// 检查 ql_tokens 表是否存在
|
// 检查 ql_tokens 表是否存在
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package executor
|
package executor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strings"
|
"strings"
|
||||||
"fmt"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -71,7 +71,6 @@ func (m *CronManager) Stop() {
|
|||||||
m.logger.Infof("[CronManager] 调度管理服务已停止")
|
m.logger.Infof("[CronManager] 调度管理服务已停止")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// AddTask 添加或更新计划任务
|
// AddTask 添加或更新计划任务
|
||||||
func (m *CronManager) AddTask(task CronTask) error {
|
func (m *CronManager) AddTask(task CronTask) error {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
@@ -109,15 +108,15 @@ func (m *CronManager) AddTask(task CronTask) error {
|
|||||||
return m.OnTrigger(task)
|
return m.OnTrigger(task)
|
||||||
}
|
}
|
||||||
return &ExecutionRequest{
|
return &ExecutionRequest{
|
||||||
TaskID: taskID,
|
TaskID: taskID,
|
||||||
Name: name,
|
Name: name,
|
||||||
Command: cmd,
|
Command: cmd,
|
||||||
PreCommand: task.GetPreCommand(),
|
PreCommand: task.GetPreCommand(),
|
||||||
PostCommand: task.GetPostCommand(),
|
PostCommand: task.GetPostCommand(),
|
||||||
Type: TaskTypeCron,
|
Type: TaskTypeCron,
|
||||||
Timeout: timeout,
|
Timeout: timeout,
|
||||||
WorkDir: workDir,
|
WorkDir: workDir,
|
||||||
Envs: func() []string {
|
Envs: func() []string {
|
||||||
if vars := task.GetEnvVars(); len(vars) > 0 {
|
if vars := task.GetEnvVars(); len(vars) > 0 {
|
||||||
return vars
|
return vars
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,10 +46,10 @@ type Request struct {
|
|||||||
PreCommand string
|
PreCommand string
|
||||||
PostCommand string
|
PostCommand string
|
||||||
WorkDir string
|
WorkDir string
|
||||||
Envs []string
|
Envs []string
|
||||||
Timeout int // 任务超时时间(分钟)
|
Timeout int // 任务超时时间(分钟)
|
||||||
Languages []map[string]string
|
Languages []map[string]string
|
||||||
UseMise bool
|
UseMise bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Result 任务执行结果
|
// Result 任务执行结果
|
||||||
|
|||||||
@@ -63,21 +63,21 @@ const (
|
|||||||
|
|
||||||
// ExecutionRequest 执行请求(标准接口)
|
// ExecutionRequest 执行请求(标准接口)
|
||||||
type ExecutionRequest struct {
|
type ExecutionRequest struct {
|
||||||
TaskID string // 任务 ID
|
TaskID string // 任务 ID
|
||||||
LogID string // 日志 ID
|
LogID string // 日志 ID
|
||||||
Name string // 任务名称
|
Name string // 任务名称
|
||||||
Type TaskType // 任务类型
|
Type TaskType // 任务类型
|
||||||
Command string // 命令
|
Command string // 命令
|
||||||
MaskedCommand string // 脱敏后的命令(用于日志和展示)
|
MaskedCommand string // 脱敏后的命令(用于日志和展示)
|
||||||
PreCommand string // 前置命令
|
PreCommand string // 前置命令
|
||||||
PostCommand string // 后置命令
|
PostCommand string // 后置命令
|
||||||
WorkDir string // 工作目录
|
WorkDir string // 工作目录
|
||||||
Envs []string // 环境变量
|
Envs []string // 环境变量
|
||||||
Secrets []string // 需要脱敏的密码
|
Secrets []string // 需要脱敏的密码
|
||||||
Timeout int // 超时时间(分钟)
|
Timeout int // 超时时间(分钟)
|
||||||
Languages []map[string]string // 语言环境配置
|
Languages []map[string]string // 语言环境配置
|
||||||
UseMise bool // 是否使用 mise
|
UseMise bool // 是否使用 mise
|
||||||
Metadata ExecutionMetadata // 额外元数据
|
Metadata ExecutionMetadata // 额外元数据
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecutionMetadata 执行额外元数据
|
// ExecutionMetadata 执行额外元数据
|
||||||
@@ -211,11 +211,11 @@ func NewScheduler(config SchedulerConfig, handler SchedulerEventHandler) *Schedu
|
|||||||
Command: req.Command,
|
Command: req.Command,
|
||||||
PreCommand: req.PreCommand,
|
PreCommand: req.PreCommand,
|
||||||
PostCommand: req.PostCommand,
|
PostCommand: req.PostCommand,
|
||||||
WorkDir: req.WorkDir,
|
WorkDir: req.WorkDir,
|
||||||
Envs: req.Envs,
|
Envs: req.Envs,
|
||||||
Timeout: req.Timeout,
|
Timeout: req.Timeout,
|
||||||
Languages: req.Languages,
|
Languages: req.Languages,
|
||||||
UseMise: req.UseMise,
|
UseMise: req.UseMise,
|
||||||
}, stdout, stderr, hooks)
|
}, stdout, stderr, hooks)
|
||||||
},
|
},
|
||||||
taskQueue: make(chan *ExecutionRequest, config.QueueSize),
|
taskQueue: make(chan *ExecutionRequest, config.QueueSize),
|
||||||
|
|||||||
+14
-14
@@ -58,9 +58,9 @@ type Agent struct {
|
|||||||
Hostname string `json:"hostname" gorm:"size:100"` // Agent 主机名
|
Hostname string `json:"hostname" gorm:"size:100"` // Agent 主机名
|
||||||
OS string `json:"os" gorm:"size:20"` // 操作系统
|
OS string `json:"os" gorm:"size:20"` // 操作系统
|
||||||
Arch string `json:"arch" gorm:"size:20"` // 架构
|
Arch string `json:"arch" gorm:"size:20"` // 架构
|
||||||
ForceUpdate bool `json:"force_update" gorm:"default:false"` // 强制更新标志
|
ForceUpdate bool `json:"force_update" gorm:"default:false"` // 强制更新标志
|
||||||
Enabled *bool `json:"enabled" gorm:"default:true"` // 是否启用
|
Enabled *bool `json:"enabled" gorm:"default:true"` // 是否启用
|
||||||
SchedulerConfig AgentSchedulerConfig `json:"scheduler_config" gorm:"type:text"` // 调度配置,以 JSON 字符串形式存储在 Text 类型字段中
|
SchedulerConfig AgentSchedulerConfig `json:"scheduler_config" gorm:"type:text"` // 调度配置,以 JSON 字符串形式存储在 Text 类型字段中
|
||||||
CreatedAt LocalTime `json:"created_at"`
|
CreatedAt LocalTime `json:"created_at"`
|
||||||
UpdatedAt LocalTime `json:"updated_at"`
|
UpdatedAt LocalTime `json:"updated_at"`
|
||||||
}
|
}
|
||||||
@@ -71,15 +71,15 @@ func (Agent) TableName() string {
|
|||||||
|
|
||||||
// AgentToken Agent 令牌
|
// AgentToken Agent 令牌
|
||||||
type AgentToken struct {
|
type AgentToken struct {
|
||||||
ID string `json:"id" gorm:"primaryKey;size:20"`
|
ID string `json:"id" gorm:"primaryKey;size:20"`
|
||||||
Token string `json:"token" gorm:"size:64;uniqueIndex;not null"` // 令牌
|
Token string `json:"token" gorm:"size:64;uniqueIndex;not null"` // 令牌
|
||||||
Remark string `json:"remark" gorm:"size:255"` // 备注
|
Remark string `json:"remark" gorm:"size:255"` // 备注
|
||||||
MaxUses int `json:"max_uses" gorm:"default:0"` // 最大使用次数,0 表示无限制
|
MaxUses int `json:"max_uses" gorm:"default:0"` // 最大使用次数,0 表示无限制
|
||||||
UsedCount int `json:"used_count" gorm:"default:0"` // 已使用次数
|
UsedCount int `json:"used_count" gorm:"default:0"` // 已使用次数
|
||||||
ExpiresAt *LocalTime `json:"expires_at"` // 过期时间,null 表示永不过期
|
ExpiresAt *LocalTime `json:"expires_at"` // 过期时间,null 表示永不过期
|
||||||
Enabled *bool `json:"enabled" gorm:"default:true"` // 是否启用
|
Enabled *bool `json:"enabled" gorm:"default:true"` // 是否启用
|
||||||
CreatedAt LocalTime `json:"created_at"`
|
CreatedAt LocalTime `json:"created_at"`
|
||||||
UpdatedAt LocalTime `json:"updated_at"`
|
UpdatedAt LocalTime `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (AgentToken) TableName() string {
|
func (AgentToken) TableName() string {
|
||||||
@@ -88,8 +88,8 @@ func (AgentToken) TableName() string {
|
|||||||
|
|
||||||
// AgentTask Agent 任务配置(用于下发给 Agent)
|
// AgentTask Agent 任务配置(用于下发给 Agent)
|
||||||
type AgentTask struct {
|
type AgentTask struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Command string `json:"command"`
|
Command string `json:"command"`
|
||||||
PreCommand string `json:"pre_command"`
|
PreCommand string `json:"pre_command"`
|
||||||
PostCommand string `json:"post_command"`
|
PostCommand string `json:"post_command"`
|
||||||
|
|||||||
+16
-17
@@ -6,17 +6,16 @@ import (
|
|||||||
|
|
||||||
// EnvironmentVariable represents an environment variable
|
// EnvironmentVariable represents an environment variable
|
||||||
type EnvironmentVariable struct {
|
type EnvironmentVariable struct {
|
||||||
ID string `json:"id" gorm:"primaryKey;size:20"`
|
ID string `json:"id" gorm:"primaryKey;size:20"`
|
||||||
Name string `json:"name" gorm:"size:255;not null"`
|
Name string `json:"name" gorm:"size:255;not null"`
|
||||||
Value BigText `json:"value"`
|
Value BigText `json:"value"`
|
||||||
Remark string `json:"remark" gorm:"size:500"`
|
Remark string `json:"remark" gorm:"size:500"`
|
||||||
Type string `json:"type" gorm:"size:20;default:'normal'"`
|
Type string `json:"type" gorm:"size:20;default:'normal'"`
|
||||||
Hidden *bool `json:"hidden" gorm:"default:true"`
|
Hidden *bool `json:"hidden" gorm:"default:true"`
|
||||||
Enabled *bool `json:"enabled" gorm:"default:true"`
|
Enabled *bool `json:"enabled" gorm:"default:true"`
|
||||||
UserID string `json:"user_id" gorm:"size:20;index"`
|
UserID string `json:"user_id" gorm:"size:20;index"`
|
||||||
CreatedAt LocalTime `json:"created_at"`
|
CreatedAt LocalTime `json:"created_at"`
|
||||||
UpdatedAt LocalTime `json:"updated_at"`
|
UpdatedAt LocalTime `json:"updated_at"`
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (EnvironmentVariable) TableName() string {
|
func (EnvironmentVariable) TableName() string {
|
||||||
@@ -25,12 +24,12 @@ func (EnvironmentVariable) TableName() string {
|
|||||||
|
|
||||||
// Script represents a script file
|
// Script represents a script file
|
||||||
type Script struct {
|
type Script struct {
|
||||||
ID string `json:"id" gorm:"primaryKey;size:20"`
|
ID string `json:"id" gorm:"primaryKey;size:20"`
|
||||||
Name string `json:"name" gorm:"size:255;not null"`
|
Name string `json:"name" gorm:"size:255;not null"`
|
||||||
Content BigText `json:"content"`
|
Content BigText `json:"content"`
|
||||||
UserID string `json:"user_id" gorm:"size:20;index"`
|
UserID string `json:"user_id" gorm:"size:20;index"`
|
||||||
CreatedAt LocalTime `json:"created_at"`
|
CreatedAt LocalTime `json:"created_at"`
|
||||||
UpdatedAt LocalTime `json:"updated_at"`
|
UpdatedAt LocalTime `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Script) TableName() string {
|
func (Script) TableName() string {
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Language struct {
|
type Language struct {
|
||||||
ID string `json:"id" gorm:"primaryKey;size:20"`
|
ID string `json:"id" gorm:"primaryKey;size:20"`
|
||||||
Plugin string `json:"plugin" gorm:"size:100;not null;index"`
|
Plugin string `json:"plugin" gorm:"size:100;not null;index"`
|
||||||
Version string `json:"version" gorm:"size:100;not null;index"`
|
Version string `json:"version" gorm:"size:100;not null;index"`
|
||||||
InstallPath string `json:"install_path" gorm:"size:255"`
|
InstallPath string `json:"install_path" gorm:"size:255"`
|
||||||
Source string `json:"source" gorm:"size:255"`
|
Source string `json:"source" gorm:"size:255"`
|
||||||
InstalledAt *LocalTime `json:"installed_at"`
|
InstalledAt *LocalTime `json:"installed_at"`
|
||||||
CreatedAt LocalTime `json:"created_at"`
|
CreatedAt LocalTime `json:"created_at"`
|
||||||
UpdatedAt LocalTime `json:"updated_at"`
|
UpdatedAt LocalTime `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Language) TableName() string {
|
func (Language) TableName() string {
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ import (
|
|||||||
|
|
||||||
// NotifyBinding 事件绑定表
|
// NotifyBinding 事件绑定表
|
||||||
type NotifyBinding struct {
|
type NotifyBinding struct {
|
||||||
ID string `json:"id" gorm:"primaryKey;size:20"`
|
ID string `json:"id" gorm:"primaryKey;size:20"`
|
||||||
Type string `json:"type" gorm:"size:20;not null;index"` // system 或 task
|
Type string `json:"type" gorm:"size:20;not null;index"` // system 或 task
|
||||||
Event string `json:"event" gorm:"size:50;not null;index"` // 事件类型
|
Event string `json:"event" gorm:"size:50;not null;index"` // 事件类型
|
||||||
WayID string `json:"way_id" gorm:"size:20;not null;index"` // 通知渠道ID
|
WayID string `json:"way_id" gorm:"size:20;not null;index"` // 通知渠道ID
|
||||||
DataID string `json:"data_id" gorm:"size:20;index"` // 关联ID,系统事件为空,任务事件为任务ID
|
DataID string `json:"data_id" gorm:"size:20;index"` // 关联ID,系统事件为空,任务事件为任务ID
|
||||||
Extra BigText `json:"extra"` // 额外配置(如是否开启日志推送等,对应 BindingExtra 结构)
|
Extra BigText `json:"extra"` // 额外配置(如是否开启日志推送等,对应 BindingExtra 结构)
|
||||||
CreatedAt LocalTime `json:"created_at"`
|
CreatedAt LocalTime `json:"created_at"`
|
||||||
UpdatedAt LocalTime `json:"updated_at"`
|
UpdatedAt LocalTime `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// BindingExtra 存储在 Extra 字段中的 JSON 配置
|
// BindingExtra 存储在 Extra 字段中的 JSON 配置
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ import (
|
|||||||
|
|
||||||
// NotifyWay 消息推送渠道
|
// NotifyWay 消息推送渠道
|
||||||
type NotifyWay struct {
|
type NotifyWay struct {
|
||||||
ID string `json:"id" gorm:"primaryKey;size:20"`
|
ID string `json:"id" gorm:"primaryKey;size:20"`
|
||||||
Name string `json:"name" gorm:"size:100;not null"`
|
Name string `json:"name" gorm:"size:100;not null"`
|
||||||
Type string `json:"type" gorm:"size:50;not null;index"`
|
Type string `json:"type" gorm:"size:50;not null;index"`
|
||||||
Config BigText `json:"config"`
|
Config BigText `json:"config"`
|
||||||
Enabled *bool `json:"enabled" gorm:"default:true;index"`
|
Enabled *bool `json:"enabled" gorm:"default:true;index"`
|
||||||
CreatedAt LocalTime `json:"created_at"`
|
CreatedAt LocalTime `json:"created_at"`
|
||||||
UpdatedAt LocalTime `json:"updated_at"`
|
UpdatedAt LocalTime `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (NotifyWay) TableName() string {
|
func (NotifyWay) TableName() string {
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ import (
|
|||||||
|
|
||||||
// Setting 系统设置
|
// Setting 系统设置
|
||||||
type Setting struct {
|
type Setting struct {
|
||||||
ID string `json:"id" gorm:"primaryKey;size:20"`
|
ID string `json:"id" gorm:"primaryKey;size:20"`
|
||||||
Section string `json:"section" gorm:"size:50;not null;index:idx_section_key"`
|
Section string `json:"section" gorm:"size:50;not null;index:idx_section_key"`
|
||||||
Key string `json:"key" gorm:"size:100;not null;index:idx_section_key"`
|
Key string `json:"key" gorm:"size:100;not null;index:idx_section_key"`
|
||||||
Value BigText `json:"value"`
|
Value BigText `json:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+41
-41
@@ -43,14 +43,14 @@ type CleanConfig struct {
|
|||||||
|
|
||||||
// RepoConfig 仓库同步配置
|
// RepoConfig 仓库同步配置
|
||||||
type RepoConfig struct {
|
type RepoConfig struct {
|
||||||
SourceType string `json:"source_type"` // url 或 git
|
SourceType string `json:"source_type"` // url 或 git
|
||||||
SourceURL string `json:"source_url"` // 源地址
|
SourceURL string `json:"source_url"` // 源地址
|
||||||
TargetPath string `json:"target_path"` // 目标路径
|
TargetPath string `json:"target_path"` // 目标路径
|
||||||
Branch string `json:"branch"` // Git 分支
|
Branch string `json:"branch"` // Git 分支
|
||||||
SparsePath string `json:"sparse_path"` // 稀疏检出路径(仅拉取指定目录或文件)
|
SparsePath string `json:"sparse_path"` // 稀疏检出路径(仅拉取指定目录或文件)
|
||||||
SingleFile bool `json:"single_file"` // 单文件模式(直接下载文件而非 sparse-checkout)
|
SingleFile bool `json:"single_file"` // 单文件模式(直接下载文件而非 sparse-checkout)
|
||||||
Proxy string `json:"proxy"` // 代理类型: none, ghproxy, mirror, custom
|
Proxy string `json:"proxy"` // 代理类型: none, ghproxy, mirror, custom
|
||||||
ProxyURL string `json:"proxy_url"` // 自定义代理地址
|
ProxyURL string `json:"proxy_url"` // 自定义代理地址
|
||||||
AuthToken string `json:"auth_token"` // 认证 Token
|
AuthToken string `json:"auth_token"` // 认证 Token
|
||||||
WhitelistPaths string `json:"whitelist_paths"` // 同步时保留的路径及脚本筛选白名单关键词,逗号或竖线分割
|
WhitelistPaths string `json:"whitelist_paths"` // 同步时保留的路径及脚本筛选白名单关键词,逗号或竖线分割
|
||||||
Blacklist string `json:"blacklist"` // 脚本筛选黑名单关键词,竖线分割
|
Blacklist string `json:"blacklist"` // 脚本筛选黑名单关键词,竖线分割
|
||||||
@@ -69,37 +69,37 @@ type TaskConfig struct {
|
|||||||
|
|
||||||
// Task 代表一个计划任务
|
// Task 代表一个计划任务
|
||||||
type Task struct {
|
type Task struct {
|
||||||
ID string `json:"id" gorm:"primaryKey;size:20"`
|
ID string `json:"id" gorm:"primaryKey;size:20"`
|
||||||
Name string `json:"name" gorm:"size:255;not null"`
|
Name string `json:"name" gorm:"size:255;not null"`
|
||||||
Remark string `json:"remark" gorm:"size:255;default:''"`
|
Remark string `json:"remark" gorm:"size:255;default:''"`
|
||||||
PinType string `json:"pin_type" gorm:"size:20;default:none;index"` // 置顶类型: constant.PinTypeNone, constant.PinTypeTop
|
PinType string `json:"pin_type" gorm:"size:20;default:none;index"` // 置顶类型: constant.PinTypeNone, constant.PinTypeTop
|
||||||
Command BigText `json:"command"` // 普通任务的命令
|
Command BigText `json:"command"` // 普通任务的命令
|
||||||
PreCommand BigText `json:"pre_command"` // 执行前的命令
|
PreCommand BigText `json:"pre_command"` // 执行前的命令
|
||||||
PostCommand BigText `json:"post_command"` // 执行后的命令
|
PostCommand BigText `json:"post_command"` // 执行后的命令
|
||||||
Tags string `json:"tags" gorm:"size:255;default:''"` // 标签,逗号分隔
|
Tags string `json:"tags" gorm:"size:255;default:''"` // 标签,逗号分隔
|
||||||
Type string `json:"type" gorm:"size:20;default:'task'"` // 任务类型: constant.TaskTypeNormal, constant.TaskTypeRepo
|
Type string `json:"type" gorm:"size:20;default:'task'"` // 任务类型: constant.TaskTypeNormal, constant.TaskTypeRepo
|
||||||
TriggerType string `json:"trigger_type" gorm:"size:25;default:'cron'"` // 触发类型: constant.TriggerTypeCron, constant.TriggerTypeBaihuStartup
|
TriggerType string `json:"trigger_type" gorm:"size:25;default:'cron'"` // 触发类型: constant.TriggerTypeCron, constant.TriggerTypeBaihuStartup
|
||||||
Config BigText `json:"config"` // 配置 JSON(仓库同步配置等)
|
Config BigText `json:"config"` // 配置 JSON(仓库同步配置等)
|
||||||
Schedule string `json:"schedule" gorm:"size:100"` // cron 表达式
|
Schedule string `json:"schedule" gorm:"size:100"` // cron 表达式
|
||||||
Timeout int `json:"timeout" gorm:"default:30"` // 超时时间(分钟),默认30分钟
|
Timeout int `json:"timeout" gorm:"default:30"` // 超时时间(分钟),默认30分钟
|
||||||
WorkDir string `json:"work_dir" gorm:"size:255;default:''"` // 工作目录,为空则使用 scripts 目录
|
WorkDir string `json:"work_dir" gorm:"size:255;default:''"` // 工作目录,为空则使用 scripts 目录
|
||||||
CleanConfig string `json:"clean_config" gorm:"size:255;default:''"` // 清理配置 JSON
|
CleanConfig string `json:"clean_config" gorm:"size:255;default:''"` // 清理配置 JSON
|
||||||
Envs BigText `json:"envs"` // 环境变量ID列表,逗号分隔
|
Envs BigText `json:"envs"` // 环境变量ID列表,逗号分隔
|
||||||
Languages TaskLanguages `json:"languages" gorm:"type:text"` // 针对本地任务的语言配置列表
|
Languages TaskLanguages `json:"languages" gorm:"type:text"` // 针对本地任务的语言配置列表
|
||||||
AgentID *string `json:"agent_id" gorm:"size:20;index"` // Agent ID,为空表示本地执行
|
AgentID *string `json:"agent_id" gorm:"size:20;index"` // Agent ID,为空表示本地执行
|
||||||
RetryCount int `json:"retry_count" gorm:"default:0"` // 失败重试次数
|
RetryCount int `json:"retry_count" gorm:"default:0"` // 失败重试次数
|
||||||
RetryInterval int `json:"retry_interval" gorm:"default:0"` // 失败重试间隔(秒)
|
RetryInterval int `json:"retry_interval" gorm:"default:0"` // 失败重试间隔(秒)
|
||||||
RandomRange int `json:"random_range" gorm:"default:0"` // 随机延迟范围(秒)
|
RandomRange int `json:"random_range" gorm:"default:0"` // 随机延迟范围(秒)
|
||||||
Enabled *bool `json:"enabled" gorm:"default:true"`
|
Enabled *bool `json:"enabled" gorm:"default:true"`
|
||||||
RunningGo BigText `json:"running_go"` // 正在运行的 go routine id 数组 (JSON)
|
RunningGo BigText `json:"running_go"` // 正在运行的 go routine id 数组 (JSON)
|
||||||
RuntimeEnvs []string `json:"-" gorm:"-"` // 运行时环境变量(非持久化)
|
RuntimeEnvs []string `json:"-" gorm:"-"` // 运行时环境变量(非持久化)
|
||||||
RuntimeSecrets []string `json:"-" gorm:"-"` // 运行时安全机密(非持久化)
|
RuntimeSecrets []string `json:"-" gorm:"-"` // 运行时安全机密(非持久化)
|
||||||
LastRun *LocalTime `json:"last_run"`
|
LastRun *LocalTime `json:"last_run"`
|
||||||
NextRun *LocalTime `json:"next_run"`
|
NextRun *LocalTime `json:"next_run"`
|
||||||
SourceID string `json:"source_id" gorm:"size:255;index"` // 脚本资源唯一标识(路径 sanitized)
|
SourceID string `json:"source_id" gorm:"size:255;index"` // 脚本资源唯一标识(路径 sanitized)
|
||||||
RepoTaskID string `json:"repo_task_id" gorm:"size:20;index"` // 所属的仓库任务 ID
|
RepoTaskID string `json:"repo_task_id" gorm:"size:20;index"` // 所属的仓库任务 ID
|
||||||
CreatedAt LocalTime `json:"created_at"`
|
CreatedAt LocalTime `json:"created_at"`
|
||||||
UpdatedAt LocalTime `json:"updated_at"`
|
UpdatedAt LocalTime `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Task) IsRunning() bool {
|
func (t *Task) IsRunning() bool {
|
||||||
@@ -180,8 +180,8 @@ type TaskLog struct {
|
|||||||
TaskID string `json:"task_id" gorm:"size:20;index"`
|
TaskID string `json:"task_id" gorm:"size:20;index"`
|
||||||
AgentID *string `json:"agent_id" gorm:"size:20;index"` // Agent ID,为空表示本地执行
|
AgentID *string `json:"agent_id" gorm:"size:20;index"` // Agent ID,为空表示本地执行
|
||||||
Command BigText `json:"command"`
|
Command BigText `json:"command"`
|
||||||
Output BigText `json:"-"` // gzip+base64 压缩后的日志
|
Output BigText `json:"-"` // gzip+base64 压缩后的日志
|
||||||
Error BigText `json:"error"` // 额外的系统错误信息
|
Error BigText `json:"error"` // 额外的系统错误信息
|
||||||
Status string `json:"status" gorm:"size:20;index"` // success, failed
|
Status string `json:"status" gorm:"size:20;index"` // success, failed
|
||||||
Duration int64 `json:"duration"` // 执行耗时(毫秒)
|
Duration int64 `json:"duration"` // 执行耗时(毫秒)
|
||||||
ExitCode int `json:"exit_code"`
|
ExitCode int `json:"exit_code"`
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ import (
|
|||||||
|
|
||||||
// User represents a system user
|
// User represents a system user
|
||||||
type User struct {
|
type User struct {
|
||||||
ID string `json:"id" gorm:"primaryKey;size:20"`
|
ID string `json:"id" gorm:"primaryKey;size:20"`
|
||||||
Username string `json:"username" gorm:"size:100;uniqueIndex;not null"`
|
Username string `json:"username" gorm:"size:100;uniqueIndex;not null"`
|
||||||
Password string `json:"password" gorm:"size:255;not null"`
|
Password string `json:"password" gorm:"size:255;not null"`
|
||||||
Email string `json:"email" gorm:"size:255"`
|
Email string `json:"email" gorm:"size:255"`
|
||||||
Role string `json:"role" gorm:"size:20;default:user"` // admin, user
|
Role string `json:"role" gorm:"size:20;default:user"` // admin, user
|
||||||
TokenVersion int `json:"-" gorm:"default:1"` // 用于 JWT 失效校验
|
TokenVersion int `json:"-" gorm:"default:1"` // 用于 JWT 失效校验
|
||||||
CreatedAt LocalTime `json:"created_at"`
|
CreatedAt LocalTime `json:"created_at"`
|
||||||
UpdatedAt LocalTime `json:"updated_at"`
|
UpdatedAt LocalTime `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (User) TableName() string {
|
func (User) TableName() string {
|
||||||
|
|||||||
@@ -9,17 +9,17 @@ import (
|
|||||||
|
|
||||||
// AgentVO 代理视图对象
|
// AgentVO 代理视图对象
|
||||||
type AgentVO struct {
|
type AgentVO struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
LastSeen *models.LocalTime `json:"last_seen"`
|
LastSeen *models.LocalTime `json:"last_seen"`
|
||||||
IP string `json:"ip"`
|
IP string `json:"ip"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
BuildTime string `json:"build_time"`
|
BuildTime string `json:"build_time"`
|
||||||
Hostname string `json:"hostname"`
|
Hostname string `json:"hostname"`
|
||||||
OS string `json:"os"`
|
OS string `json:"os"`
|
||||||
Arch string `json:"arch"`
|
Arch string `json:"arch"`
|
||||||
ForceUpdate bool `json:"force_update"`
|
ForceUpdate bool `json:"force_update"`
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
SchedulerConfig *AgentSchedulerConfigVO `json:"scheduler_config"`
|
SchedulerConfig *AgentSchedulerConfigVO `json:"scheduler_config"`
|
||||||
@@ -44,17 +44,17 @@ func ToAgentVO(agent *models.Agent) *AgentVO {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &AgentVO{
|
return &AgentVO{
|
||||||
ID: agent.ID,
|
ID: agent.ID,
|
||||||
Name: agent.Name,
|
Name: agent.Name,
|
||||||
Description: agent.Description,
|
Description: agent.Description,
|
||||||
Status: agent.Status,
|
Status: agent.Status,
|
||||||
LastSeen: agent.LastSeen,
|
LastSeen: agent.LastSeen,
|
||||||
IP: agent.IP,
|
IP: agent.IP,
|
||||||
Version: agent.Version,
|
Version: agent.Version,
|
||||||
BuildTime: agent.BuildTime,
|
BuildTime: agent.BuildTime,
|
||||||
Hostname: agent.Hostname,
|
Hostname: agent.Hostname,
|
||||||
OS: agent.OS,
|
OS: agent.OS,
|
||||||
Arch: agent.Arch,
|
Arch: agent.Arch,
|
||||||
ForceUpdate: agent.ForceUpdate,
|
ForceUpdate: agent.ForceUpdate,
|
||||||
Enabled: utils.DerefBool(agent.Enabled, true),
|
Enabled: utils.DerefBool(agent.Enabled, true),
|
||||||
SchedulerConfig: schedulerConfigVO,
|
SchedulerConfig: schedulerConfigVO,
|
||||||
|
|||||||
@@ -8,34 +8,34 @@ import (
|
|||||||
|
|
||||||
// TaskVO 任务视图对象
|
// TaskVO 任务视图对象
|
||||||
type TaskVO struct {
|
type TaskVO struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Remark string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
Command string `json:"command"`
|
Command string `json:"command"`
|
||||||
PreCommand string `json:"pre_command"`
|
PreCommand string `json:"pre_command"`
|
||||||
PostCommand string `json:"post_command"`
|
PostCommand string `json:"post_command"`
|
||||||
Tags string `json:"tags"`
|
Tags string `json:"tags"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
TriggerType string `json:"trigger_type"`
|
TriggerType string `json:"trigger_type"`
|
||||||
Config string `json:"config"`
|
Config string `json:"config"`
|
||||||
Schedule string `json:"schedule"`
|
Schedule string `json:"schedule"`
|
||||||
Timeout int `json:"timeout"`
|
Timeout int `json:"timeout"`
|
||||||
WorkDir string `json:"work_dir"`
|
WorkDir string `json:"work_dir"`
|
||||||
CleanConfig string `json:"clean_config"`
|
CleanConfig string `json:"clean_config"`
|
||||||
Envs string `json:"envs"`
|
Envs string `json:"envs"`
|
||||||
Languages models.TaskLanguages `json:"languages"`
|
Languages models.TaskLanguages `json:"languages"`
|
||||||
AgentID *string `json:"agent_id"`
|
AgentID *string `json:"agent_id"`
|
||||||
RepoTaskID string `json:"repo_task_id"`
|
RepoTaskID string `json:"repo_task_id"`
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
RetryCount int `json:"retry_count"`
|
RetryCount int `json:"retry_count"`
|
||||||
RetryInterval int `json:"retry_interval"`
|
RetryInterval int `json:"retry_interval"`
|
||||||
RandomRange int `json:"random_range"`
|
RandomRange int `json:"random_range"`
|
||||||
PinType string `json:"pin_type"`
|
PinType string `json:"pin_type"`
|
||||||
LastRun *models.LocalTime `json:"last_run"`
|
LastRun *models.LocalTime `json:"last_run"`
|
||||||
NextRun *models.LocalTime `json:"next_run"`
|
NextRun *models.LocalTime `json:"next_run"`
|
||||||
CreatedAt models.LocalTime `json:"created_at"`
|
CreatedAt models.LocalTime `json:"created_at"`
|
||||||
UpdatedAt models.LocalTime `json:"updated_at"`
|
UpdatedAt models.LocalTime `json:"updated_at"`
|
||||||
RunningStatus string `json:"running_status"`
|
RunningStatus string `json:"running_status"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToTaskVO 将 Task 模型转换为 TaskVO
|
// ToTaskVO 将 Task 模型转换为 TaskVO
|
||||||
@@ -44,22 +44,22 @@ func ToTaskVO(task *models.Task) *TaskVO {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &TaskVO{
|
return &TaskVO{
|
||||||
ID: task.ID,
|
ID: task.ID,
|
||||||
Name: task.Name,
|
Name: task.Name,
|
||||||
Remark: task.Remark,
|
Remark: task.Remark,
|
||||||
Command: string(task.Command),
|
Command: string(task.Command),
|
||||||
PreCommand: string(task.PreCommand),
|
PreCommand: string(task.PreCommand),
|
||||||
PostCommand: string(task.PostCommand),
|
PostCommand: string(task.PostCommand),
|
||||||
Tags: task.Tags,
|
Tags: task.Tags,
|
||||||
Type: task.Type,
|
Type: task.Type,
|
||||||
TriggerType: task.TriggerType,
|
TriggerType: task.TriggerType,
|
||||||
Config: string(task.Config),
|
Config: string(task.Config),
|
||||||
Schedule: task.Schedule,
|
Schedule: task.Schedule,
|
||||||
Timeout: task.Timeout,
|
Timeout: task.Timeout,
|
||||||
WorkDir: task.WorkDir,
|
WorkDir: task.WorkDir,
|
||||||
CleanConfig: task.CleanConfig,
|
CleanConfig: task.CleanConfig,
|
||||||
Envs: string(task.Envs),
|
Envs: string(task.Envs),
|
||||||
Languages: task.Languages,
|
Languages: task.Languages,
|
||||||
AgentID: task.AgentID,
|
AgentID: task.AgentID,
|
||||||
RepoTaskID: task.RepoTaskID,
|
RepoTaskID: task.RepoTaskID,
|
||||||
Enabled: utils.DerefBool(task.Enabled, true),
|
Enabled: utils.DerefBool(task.Enabled, true),
|
||||||
@@ -68,9 +68,9 @@ func ToTaskVO(task *models.Task) *TaskVO {
|
|||||||
RandomRange: task.RandomRange,
|
RandomRange: task.RandomRange,
|
||||||
PinType: task.PinType,
|
PinType: task.PinType,
|
||||||
LastRun: task.LastRun,
|
LastRun: task.LastRun,
|
||||||
NextRun: task.NextRun,
|
NextRun: task.NextRun,
|
||||||
CreatedAt: task.CreatedAt,
|
CreatedAt: task.CreatedAt,
|
||||||
UpdatedAt: task.UpdatedAt,
|
UpdatedAt: task.UpdatedAt,
|
||||||
RunningStatus: func() string {
|
RunningStatus: func() string {
|
||||||
if task.IsRunning() {
|
if task.IsRunning() {
|
||||||
return "running"
|
return "running"
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ func setupEventHandlers(subscribers ...eventbus.Subscriber) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func startAppLogCleanup(appLogSvc *services.AppLogService) {
|
func startAppLogCleanup(appLogSvc *services.AppLogService) {
|
||||||
// 初始化时执行一次清理
|
// 初始化时执行一次清理
|
||||||
appLogSvc.CleanUp()
|
appLogSvc.CleanUp()
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/engigu/baihu-panel/internal/controllers"
|
"github.com/engigu/baihu-panel/internal/controllers"
|
||||||
"github.com/engigu/baihu-panel/internal/middleware"
|
"github.com/engigu/baihu-panel/internal/middleware"
|
||||||
|
|||||||
@@ -132,7 +132,6 @@ func initPWARoutes(root *gin.RouterGroup) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func handleManifest(ctx *gin.Context) {
|
func handleManifest(ctx *gin.Context) {
|
||||||
staticFS := static.GetFS()
|
staticFS := static.GetFS()
|
||||||
if staticFS == nil {
|
if staticFS == nil {
|
||||||
|
|||||||
@@ -15,15 +15,15 @@ func (c *BarkChannel) Send(config ChannelConfig, msg *Message) (*Result, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cli := message.Bark{
|
cli := message.Bark{
|
||||||
PushKey: pushKey,
|
PushKey: pushKey,
|
||||||
Archive: config.GetString("archive"),
|
Archive: config.GetString("archive"),
|
||||||
Group: config.GetString("group"),
|
Group: config.GetString("group"),
|
||||||
Sound: config.GetString("sound"),
|
Sound: config.GetString("sound"),
|
||||||
Icon: config.GetString("icon"),
|
Icon: config.GetString("icon"),
|
||||||
Level: config.GetString("level"),
|
Level: config.GetString("level"),
|
||||||
URL: config.GetString("url"),
|
URL: config.GetString("url"),
|
||||||
Key: config.GetString("key"),
|
Key: config.GetString("key"),
|
||||||
IV: config.GetString("iv"),
|
IV: config.GetString("iv"),
|
||||||
Server: config.GetString("server"),
|
Server: config.GetString("server"),
|
||||||
Badge: config.GetString("badge"),
|
Badge: config.GetString("badge"),
|
||||||
Copy: config.GetString("copy"),
|
Copy: config.GetString("copy"),
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ func NewBaseChannel(channelType string, supportedFormats []string) *BaseChannel
|
|||||||
return &BaseChannel{channelType: channelType, supportedFormats: supportedFormats}
|
return &BaseChannel{channelType: channelType, supportedFormats: supportedFormats}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *BaseChannel) GetType() string { return c.channelType }
|
func (c *BaseChannel) GetType() string { return c.channelType }
|
||||||
func (c *BaseChannel) GetSupportedFormats() []string { return c.supportedFormats }
|
func (c *BaseChannel) GetSupportedFormats() []string { return c.supportedFormats }
|
||||||
|
|
||||||
// FormatContent 根据渠道支持的格式选择最佳内容
|
// FormatContent 根据渠道支持的格式选择最佳内容
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ import (
|
|||||||
|
|
||||||
"github.com/engigu/baihu-panel/internal/constant"
|
"github.com/engigu/baihu-panel/internal/constant"
|
||||||
"github.com/engigu/baihu-panel/internal/database"
|
"github.com/engigu/baihu-panel/internal/database"
|
||||||
"github.com/engigu/baihu-panel/internal/logger"
|
|
||||||
"github.com/engigu/baihu-panel/internal/executor"
|
"github.com/engigu/baihu-panel/internal/executor"
|
||||||
|
"github.com/engigu/baihu-panel/internal/logger"
|
||||||
"github.com/engigu/baihu-panel/internal/models"
|
"github.com/engigu/baihu-panel/internal/models"
|
||||||
"github.com/engigu/baihu-panel/internal/services/tasks"
|
"github.com/engigu/baihu-panel/internal/services/tasks"
|
||||||
"github.com/engigu/baihu-panel/internal/utils"
|
"github.com/engigu/baihu-panel/internal/utils"
|
||||||
@@ -378,7 +378,6 @@ func (s *AgentService) GetTasks(agentID string) []models.AgentTask {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ReportResult Agent 上报执行结果
|
// ReportResult Agent 上报执行结果
|
||||||
func (s *AgentService) ReportResult(result *models.AgentTaskResult) error {
|
func (s *AgentService) ReportResult(result *models.AgentTaskResult) error {
|
||||||
// 获取依赖的服务
|
// 获取依赖的服务
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ import (
|
|||||||
// AgentWSManager WebSocket 连接管理器
|
// AgentWSManager WebSocket 连接管理器
|
||||||
type AgentWSManager struct {
|
type AgentWSManager struct {
|
||||||
connections map[string]*AgentConnection // Agent ID -> 连接对象
|
connections map[string]*AgentConnection // Agent ID -> 连接对象
|
||||||
ipConnections map[string]int // IP -> 连接数
|
ipConnections map[string]int // IP -> 连接数
|
||||||
ipLastAttempt map[string]time.Time // IP -> 最后连接尝试时间
|
ipLastAttempt map[string]time.Time // IP -> 最后连接尝试时间
|
||||||
ipFailCount map[string]int // IP -> 连续失败次数
|
ipFailCount map[string]int // IP -> 连续失败次数
|
||||||
remoteWaiters map[string]chan *models.AgentTaskResult // 日志 ID -> 结果通道
|
remoteWaiters map[string]chan *models.AgentTaskResult // 日志 ID -> 结果通道
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -372,7 +372,6 @@ func (s *BackupService) restoreScriptsDir(r *zip.ReadCloser) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (s *BackupService) addDirToZip(zipWriter *zip.Writer, srcDir, prefix string) error {
|
func (s *BackupService) addDirToZip(zipWriter *zip.Writer, srcDir, prefix string) error {
|
||||||
return filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
|
return filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -160,8 +160,6 @@ func LoadConfig(path string) (*AppConfig, error) {
|
|||||||
return Config, nil
|
return Config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// applyEnvOverrides 从环境变量加载配置
|
// applyEnvOverrides 从环境变量加载配置
|
||||||
func applyEnvOverrides() {
|
func applyEnvOverrides() {
|
||||||
// Server
|
// Server
|
||||||
|
|||||||
@@ -109,7 +109,6 @@ func (s *MiseService) fetchLiveLanguages() ([]MiseLanguage, error) {
|
|||||||
return s.listFallback()
|
return s.listFallback()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (s *MiseService) listFallback() ([]MiseLanguage, error) {
|
func (s *MiseService) listFallback() ([]MiseLanguage, error) {
|
||||||
cmd := exec.Command("mise", "ls")
|
cmd := exec.Command("mise", "ls")
|
||||||
cmd.Env = os.Environ()
|
cmd.Env = os.Environ()
|
||||||
@@ -286,7 +285,7 @@ func (s *MiseService) syncToDB(languages []MiseLanguage) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if queryErr == nil && rowsAffected == 0 {
|
if queryErr == nil && rowsAffected == 0 {
|
||||||
// 如果不存在,则创建
|
// 如果不存在,则创建
|
||||||
newLang := models.Language{
|
newLang := models.Language{
|
||||||
ID: utils.GenerateID(),
|
ID: utils.GenerateID(),
|
||||||
Plugin: lang.Plugin,
|
Plugin: lang.Plugin,
|
||||||
@@ -329,6 +328,7 @@ func (s *MiseService) GetVerifyCommand(plugin, version string) (string, error) {
|
|||||||
}
|
}
|
||||||
return m.GetVerifyCommand(version)
|
return m.GetVerifyCommand(version)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UseGlobal 设置全局默认版本
|
// UseGlobal 设置全局默认版本
|
||||||
func (s *MiseService) UseGlobal(plugin, version string) error {
|
func (s *MiseService) UseGlobal(plugin, version string) error {
|
||||||
cmd := exec.Command("mise", "use", "-g", fmt.Sprintf("%s@%s", plugin, version))
|
cmd := exec.Command("mise", "use", "-g", fmt.Sprintf("%s@%s", plugin, version))
|
||||||
@@ -355,6 +355,7 @@ func (s *MiseService) UnsetGlobal(plugin, version string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Envs 获取全局环境变量
|
// Envs 获取全局环境变量
|
||||||
func (s *MiseService) Envs() (map[string]string, error) {
|
func (s *MiseService) Envs() (map[string]string, error) {
|
||||||
cmd := exec.Command("mise", "set")
|
cmd := exec.Command("mise", "set")
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package repo
|
package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/engigu/baihu-panel/internal/models"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"github.com/engigu/baihu-panel/internal/models"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// QinglongStrategy 实现与青龙兼容的解析逻辑
|
// QinglongStrategy 实现与青龙兼容的解析逻辑
|
||||||
|
|||||||
@@ -3,17 +3,17 @@ package repo
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/engigu/baihu-panel/internal/utils"
|
||||||
|
"github.com/robfig/cron/v3"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"github.com/engigu/baihu-panel/internal/utils"
|
|
||||||
"github.com/robfig/cron/v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// envRegex 匹配脚本中的环境名称设置,如 Env("名称")
|
// envRegex 匹配脚本中的环境名称设置,如 Env("名称")
|
||||||
envRegex = regexp.MustCompile(`(?i)(?:new[ \t]+)?Env\(['"]?([^'"]+)['"]?\)`)
|
envRegex = regexp.MustCompile(`(?i)(?:new[ \t]+)?Env\(['"]?([^'"]+)['"]?\)`)
|
||||||
// cronRegex 匹配脚本中的 cron 表达式设置
|
// cronRegex 匹配脚本中的 cron 表达式设置
|
||||||
cronRegex = regexp.MustCompile(`(?i)(?:cron[ \t]*[:=][ \t]*['"]?([^'"\r\n]+))|(?:(?:^|[ \t\*\/])(([0-9\*\/\-,L?#]+[ \t]+){4,5}[0-9\*\/\-,L?#]+))`)
|
cronRegex = regexp.MustCompile(`(?i)(?:cron[ \t]*[:=][ \t]*['"]?([^'"\r\n]+))|(?:(?:^|[ \t\*\/])(([0-9\*\/\-,L?#]+[ \t]+){4,5}[0-9\*\/\-,L?#]+))`)
|
||||||
// cronFormatRegex 用于校验提取出的字符串是否符合 Cron 表达式格式 (5位或6位)
|
// cronFormatRegex 用于校验提取出的字符串是否符合 Cron 表达式格式 (5位或6位)
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/engigu/baihu-panel/internal/constant"
|
||||||
"github.com/engigu/baihu-panel/internal/database"
|
"github.com/engigu/baihu-panel/internal/database"
|
||||||
"github.com/engigu/baihu-panel/internal/logger"
|
"github.com/engigu/baihu-panel/internal/logger"
|
||||||
"github.com/engigu/baihu-panel/internal/models"
|
"github.com/engigu/baihu-panel/internal/models"
|
||||||
"github.com/engigu/baihu-panel/internal/systime"
|
"github.com/engigu/baihu-panel/internal/systime"
|
||||||
"github.com/engigu/baihu-panel/internal/constant"
|
|
||||||
"github.com/engigu/baihu-panel/internal/utils"
|
"github.com/engigu/baihu-panel/internal/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,6 @@ func (ts *TaskService) CreateTask(p *TaskParam) *models.Task {
|
|||||||
}
|
}
|
||||||
database.DB.Select("*").Create(task)
|
database.DB.Select("*").Create(task)
|
||||||
|
|
||||||
|
|
||||||
return task
|
return task
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ type TinyLog struct {
|
|||||||
path string
|
path string
|
||||||
writer *bufio.Writer
|
writer *bufio.Writer
|
||||||
subscribers []chan []byte
|
subscribers []chan []byte
|
||||||
remainder []byte // Leftover bytes from previous write (partial lines)
|
remainder []byte // Leftover bytes from previous write (partial lines)
|
||||||
masks []string // Secrets to mask
|
masks []string // Secrets to mask
|
||||||
closed bool
|
closed bool
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
func GenerateID() string {
|
func GenerateID() string {
|
||||||
return xid.New().String()
|
return xid.New().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNumeric 检查字符串是否全为数字
|
// IsNumeric 检查字符串是否全为数字
|
||||||
func IsNumeric(s string) bool {
|
func IsNumeric(s string) bool {
|
||||||
for _, c := range s {
|
for _, c := range s {
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ var (
|
|||||||
shellOnce sync.Once
|
shellOnce sync.Once
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
// GetShell 返回当前操作系统的 shell 和参数
|
// GetShell 返回当前操作系统的 shell 和参数
|
||||||
func GetShell() (shell string, args []string) {
|
func GetShell() (shell string, args []string) {
|
||||||
shellOnce.Do(func() {
|
shellOnce.Do(func() {
|
||||||
|
|||||||
Reference in New Issue
Block a user