diff --git a/app/http/controllers/plugins/php74_controller.go b/app/http/controllers/plugins/php74_controller.go deleted file mode 100644 index 4dce0906..00000000 --- a/app/http/controllers/plugins/php74_controller.go +++ /dev/null @@ -1,273 +0,0 @@ -package plugins - -import ( - "fmt" - "regexp" - "strings" - "time" - - "github.com/goravel/framework/contracts/http" - "github.com/goravel/framework/facades" - "github.com/imroc/req/v3" - - "panel/app/http/controllers" - "panel/app/models" - "panel/internal" - "panel/internal/services" - "panel/pkg/tools" -) - -type Php74Controller struct { - setting internal.Setting - task internal.Task - version string -} - -func NewPhp74Controller() *Php74Controller { - return &Php74Controller{ - setting: services.NewSettingImpl(), - task: services.NewTaskImpl(), - version: "74", - } -} - -func (r *Php74Controller) Status(ctx http.Context) http.Response { - status, err := tools.ServiceStatus("php-fpm-" + r.version) - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败") - } - - return controllers.Success(ctx, status) -} - -func (r *Php74Controller) Reload(ctx http.Context) http.Response { - if err := tools.ServiceReload("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "重载PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php74Controller) Start(ctx http.Context) http.Response { - if err := tools.ServiceStart("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "启动PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php74Controller) Stop(ctx http.Context) http.Response { - if err := tools.ServiceStop("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "停止PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php74Controller) Restart(ctx http.Context) http.Response { - if err := tools.ServiceRestart("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "重启PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php74Controller) GetConfig(ctx http.Context) http.Response { - config, err := tools.Read("/www/server/php/" + r.version + "/etc/php.ini") - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"配置失败") - } - - return controllers.Success(ctx, config) -} - -func (r *Php74Controller) SaveConfig(ctx http.Context) http.Response { - config := ctx.Request().Input("config") - if err := tools.Write("/www/server/php/"+r.version+"/etc/php.ini", config, 0644); err != nil { - return nil - } - return r.Reload(ctx) -} - -func (r *Php74Controller) Load(ctx http.Context) http.Response { - client := req.C().SetTimeout(10 * time.Second) - resp, err := client.R().Get("http://127.0.0.1/phpfpm_status/" + r.version) - if err != nil || !resp.IsSuccessState() { - facades.Log().Info("获取PHP-" + r.version + "运行状态失败") - return controllers.Error(ctx, http.StatusInternalServerError, "[PHP-"+r.version+"] 获取运行状态失败") - } - - raw := resp.String() - dataKeys := []string{"应用池", "工作模式", "启动时间", "接受连接", "监听队列", "最大监听队列", "监听队列长度", "空闲进程数量", "活动进程数量", "总进程数量", "最大活跃进程数量", "达到进程上限次数", "慢请求"} - regexKeys := []string{"pool", "process manager", "start time", "accepted conn", "listen queue", "max listen queue", "listen queue len", "idle processes", "active processes", "total processes", "max active processes", "max children reached", "slow requests"} - - type Data struct { - Name string `json:"name"` - Value string `json:"value"` - } - data := make([]Data, len(dataKeys)) - for i := range dataKeys { - data[i].Name = dataKeys[i] - - r := regexp.MustCompile(fmt.Sprintf("%s:\\s+(.*)", regexKeys[i])) - match := r.FindStringSubmatch(raw) - - if len(match) > 1 { - data[i].Value = strings.TrimSpace(match[1]) - } - } - - return controllers.Success(ctx, data) -} - -func (r *Php74Controller) ErrorLog(ctx http.Context) http.Response { - log, _ := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/php-fpm.log") - return controllers.Success(ctx, log) -} - -func (r *Php74Controller) SlowLog(ctx http.Context) http.Response { - log, _ := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/slow.log") - return controllers.Success(ctx, log) -} - -func (r *Php74Controller) ClearErrorLog(ctx http.Context) http.Response { - if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/php-fpm.log"); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - - return controllers.Success(ctx, nil) -} - -func (r *Php74Controller) ClearSlowLog(ctx http.Context) http.Response { - if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/slow.log"); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - return controllers.Success(ctx, nil) -} - -func (r *Php74Controller) GetExtensionList(ctx http.Context) http.Response { - extensions := r.GetExtensions() - return controllers.Success(ctx, extensions) -} - -func (r *Php74Controller) InstallExtension(ctx http.Context) http.Response { - slug := ctx.Request().Input("slug") - if len(slug) == 0 { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误") - } - - extensions := r.GetExtensions() - for _, item := range extensions { - if item.Slug == slug { - if item.Installed { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展已安装") - } - - var task models.Task - task.Name = "安装PHP-" + r.version + "扩展-" + item.Name - task.Status = models.TaskStatusWaiting - task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' install ` + r.version + ` >> '/tmp/` + item.Slug + `.log' 2>&1` - task.Log = "/tmp/" + item.Slug + ".log" - if err := facades.Orm().Query().Create(&task); err != nil { - facades.Log().Info("[PHP-" + r.version + "] 创建安装拓展任务失败:" + err.Error()) - return controllers.ErrorSystem(ctx) - } - - r.task.Process(task.ID) - - return controllers.Success(ctx, true) - } - } - - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在") -} - -func (r *Php74Controller) UninstallExtension(ctx http.Context) http.Response { - slug := ctx.Request().Input("slug") - if len(slug) == 0 { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误") - } - - extensions := r.GetExtensions() - for _, item := range extensions { - if item.Slug == slug { - if !item.Installed { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展未安装") - } - - var task models.Task - task.Name = "卸载PHP-" + r.version + "扩展-" + item.Name - task.Status = models.TaskStatusWaiting - task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' uninstall ` + r.version + ` >> '/tmp/` + item.Slug + `.log' 2>&1` - task.Log = "/tmp/" + item.Slug + ".log" - if err := facades.Orm().Query().Create(&task); err != nil { - facades.Log().Info("[PHP-" + r.version + "] 创建卸载拓展任务失败:" + err.Error()) - return controllers.ErrorSystem(ctx) - } - - r.task.Process(task.ID) - - return controllers.Success(ctx, true) - } - } - - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在") -} - -func (r *Php74Controller) GetExtensions() []PHPExtension { - var extensions []PHPExtension - extensions = append(extensions, PHPExtension{ - Name: "OPcache", - Slug: "Zend OPcache", - Description: "OPcache 通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的性能,存储预编译字节码可以省去每次加载和解析 PHP 脚本的开销。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "PhpRedis", - Slug: "redis", - Description: "PhpRedis 是一个用 C 语言编写的 PHP 模块,用来连接并操作 Redis 数据库上的数据。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "ImageMagick", - Slug: "imagick", - Description: "ImageMagick 是一个免费的创建、编辑、合成图片的软件。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "Exif", - Slug: "exif", - Description: "通过 exif 扩展,你可以操作图像元数据。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "pdo_pgsql", - Slug: "pdo_pgsql", - Description: "(需先安装PostgreSQL)pdo_pgsql 是一个驱动程序,它实现了 PHP 数据对象(PDO)接口以启用从 PHP 到 PostgreSQL 数据库的访问。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "ionCube", - Slug: "ionCube Loader", - Description: "ionCube 是一个专业级的 PHP 加密解密工具。", - Installed: false, - }) - - raw, err := tools.Exec("/www/server/php/" + r.version + "/bin/php -m") - if err != nil { - return extensions - } - - rawExtensionList := strings.Split(raw, "\n") - for _, item := range rawExtensionList { - if !strings.Contains(item, "[") && item != "" { - for i := range extensions { - if extensions[i].Slug == item { - extensions[i].Installed = true - } - } - } - } - - return extensions -} diff --git a/app/http/controllers/plugins/php80_controller.go b/app/http/controllers/plugins/php80_controller.go deleted file mode 100644 index a4a19c53..00000000 --- a/app/http/controllers/plugins/php80_controller.go +++ /dev/null @@ -1,273 +0,0 @@ -package plugins - -import ( - "fmt" - "regexp" - "strings" - "time" - - "github.com/goravel/framework/contracts/http" - "github.com/goravel/framework/facades" - "github.com/imroc/req/v3" - - "panel/app/http/controllers" - "panel/app/models" - "panel/internal" - "panel/internal/services" - "panel/pkg/tools" -) - -type Php80Controller struct { - setting internal.Setting - task internal.Task - version string -} - -func NewPhp80Controller() *Php80Controller { - return &Php80Controller{ - setting: services.NewSettingImpl(), - task: services.NewTaskImpl(), - version: "80", - } -} - -func (r *Php80Controller) Status(ctx http.Context) http.Response { - status, err := tools.ServiceStatus("php-fpm-" + r.version) - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败") - } - - return controllers.Success(ctx, status) -} - -func (r *Php80Controller) Reload(ctx http.Context) http.Response { - if err := tools.ServiceReload("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "重载PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php80Controller) Start(ctx http.Context) http.Response { - if err := tools.ServiceStart("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "启动PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php80Controller) Stop(ctx http.Context) http.Response { - if err := tools.ServiceStop("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "停止PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php80Controller) Restart(ctx http.Context) http.Response { - if err := tools.ServiceRestart("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "重启PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php80Controller) GetConfig(ctx http.Context) http.Response { - config, err := tools.Read("/www/server/php/" + r.version + "/etc/php.ini") - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"配置失败") - } - - return controllers.Success(ctx, config) -} - -func (r *Php80Controller) SaveConfig(ctx http.Context) http.Response { - config := ctx.Request().Input("config") - if err := tools.Write("/www/server/php/"+r.version+"/etc/php.ini", config, 0644); err != nil { - return nil - } - return r.Reload(ctx) -} - -func (r *Php80Controller) Load(ctx http.Context) http.Response { - client := req.C().SetTimeout(10 * time.Second) - resp, err := client.R().Get("http://127.0.0.1/phpfpm_status/" + r.version) - if err != nil || !resp.IsSuccessState() { - facades.Log().Info("获取PHP-" + r.version + "运行状态失败") - return controllers.Error(ctx, http.StatusInternalServerError, "[PHP-"+r.version+"] 获取运行状态失败") - } - - raw := resp.String() - dataKeys := []string{"应用池", "工作模式", "启动时间", "接受连接", "监听队列", "最大监听队列", "监听队列长度", "空闲进程数量", "活动进程数量", "总进程数量", "最大活跃进程数量", "达到进程上限次数", "慢请求"} - regexKeys := []string{"pool", "process manager", "start time", "accepted conn", "listen queue", "max listen queue", "listen queue len", "idle processes", "active processes", "total processes", "max active processes", "max children reached", "slow requests"} - - type Data struct { - Name string `json:"name"` - Value string `json:"value"` - } - data := make([]Data, len(dataKeys)) - for i := range dataKeys { - data[i].Name = dataKeys[i] - - r := regexp.MustCompile(fmt.Sprintf("%s:\\s+(.*)", regexKeys[i])) - match := r.FindStringSubmatch(raw) - - if len(match) > 1 { - data[i].Value = strings.TrimSpace(match[1]) - } - } - - return controllers.Success(ctx, data) -} - -func (r *Php80Controller) ErrorLog(ctx http.Context) http.Response { - log, _ := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/php-fpm.log") - return controllers.Success(ctx, log) -} - -func (r *Php80Controller) SlowLog(ctx http.Context) http.Response { - log, _ := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/slow.log") - return controllers.Success(ctx, log) -} - -func (r *Php80Controller) ClearErrorLog(ctx http.Context) http.Response { - if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/php-fpm.log"); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - - return controllers.Success(ctx, nil) -} - -func (r *Php80Controller) ClearSlowLog(ctx http.Context) http.Response { - if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/slow.log"); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - return controllers.Success(ctx, nil) -} - -func (r *Php80Controller) GetExtensionList(ctx http.Context) http.Response { - extensions := r.GetExtensions() - return controllers.Success(ctx, extensions) -} - -func (r *Php80Controller) InstallExtension(ctx http.Context) http.Response { - slug := ctx.Request().Input("slug") - if len(slug) == 0 { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误") - } - - extensions := r.GetExtensions() - for _, item := range extensions { - if item.Slug == slug { - if item.Installed { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展已安装") - } - - var task models.Task - task.Name = "安装PHP-" + r.version + "扩展-" + item.Name - task.Status = models.TaskStatusWaiting - task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' install ` + r.version + ` >> '/tmp/` + item.Slug + `.log' 2>&1` - task.Log = "/tmp/" + item.Slug + ".log" - if err := facades.Orm().Query().Create(&task); err != nil { - facades.Log().Info("[PHP-" + r.version + "] 创建安装拓展任务失败:" + err.Error()) - return controllers.ErrorSystem(ctx) - } - - r.task.Process(task.ID) - - return controllers.Success(ctx, true) - } - } - - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在") -} - -func (r *Php80Controller) UninstallExtension(ctx http.Context) http.Response { - slug := ctx.Request().Input("slug") - if len(slug) == 0 { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误") - } - - extensions := r.GetExtensions() - for _, item := range extensions { - if item.Slug == slug { - if !item.Installed { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展未安装") - } - - var task models.Task - task.Name = "卸载PHP-" + r.version + "扩展-" + item.Name - task.Status = models.TaskStatusWaiting - task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' uninstall ` + r.version + ` >> '/tmp/` + item.Slug + `.log' 2>&1` - task.Log = "/tmp/" + item.Slug + ".log" - if err := facades.Orm().Query().Create(&task); err != nil { - facades.Log().Info("[PHP-" + r.version + "] 创建卸载拓展任务失败:" + err.Error()) - return controllers.ErrorSystem(ctx) - } - - r.task.Process(task.ID) - - return controllers.Success(ctx, true) - } - } - - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在") -} - -func (r *Php80Controller) GetExtensions() []PHPExtension { - var extensions []PHPExtension - extensions = append(extensions, PHPExtension{ - Name: "OPcache", - Slug: "Zend OPcache", - Description: "OPcache 通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的性能,存储预编译字节码可以省去每次加载和解析 PHP 脚本的开销。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "PhpRedis", - Slug: "redis", - Description: "PhpRedis 是一个用 C 语言编写的 PHP 模块,用来连接并操作 Redis 数据库上的数据。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "ImageMagick", - Slug: "imagick", - Description: "ImageMagick 是一个免费的创建、编辑、合成图片的软件。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "Exif", - Slug: "exif", - Description: "通过 exif 扩展,你可以操作图像元数据。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "pdo_pgsql", - Slug: "pdo_pgsql", - Description: "(需先安装PostgreSQL)pdo_pgsql 是一个驱动程序,它实现了 PHP 数据对象(PDO)接口以启用从 PHP 到 PostgreSQL 数据库的访问。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "ionCube", - Slug: "ionCube Loader", - Description: "ionCube 是一个专业级的 PHP 加密解密工具。", - Installed: false, - }) - - raw, err := tools.Exec("/www/server/php/" + r.version + "/bin/php -m") - if err != nil { - return extensions - } - - rawExtensionList := strings.Split(raw, "\n") - for _, item := range rawExtensionList { - if !strings.Contains(item, "[") && item != "" { - for i := range extensions { - if extensions[i].Slug == item { - extensions[i].Installed = true - } - } - } - } - - return extensions -} diff --git a/app/http/controllers/plugins/php81_controller.go b/app/http/controllers/plugins/php81_controller.go deleted file mode 100644 index a234dd07..00000000 --- a/app/http/controllers/plugins/php81_controller.go +++ /dev/null @@ -1,273 +0,0 @@ -package plugins - -import ( - "fmt" - "regexp" - "strings" - "time" - - "github.com/goravel/framework/contracts/http" - "github.com/goravel/framework/facades" - "github.com/imroc/req/v3" - - "panel/app/http/controllers" - "panel/app/models" - "panel/internal" - "panel/internal/services" - "panel/pkg/tools" -) - -type Php81Controller struct { - setting internal.Setting - task internal.Task - version string -} - -func NewPhp81Controller() *Php81Controller { - return &Php81Controller{ - setting: services.NewSettingImpl(), - task: services.NewTaskImpl(), - version: "81", - } -} - -func (r *Php81Controller) Status(ctx http.Context) http.Response { - status, err := tools.ServiceStatus("php-fpm-" + r.version) - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败") - } - - return controllers.Success(ctx, status) -} - -func (r *Php81Controller) Reload(ctx http.Context) http.Response { - if err := tools.ServiceReload("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "重载PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php81Controller) Start(ctx http.Context) http.Response { - if err := tools.ServiceStart("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "启动PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php81Controller) Stop(ctx http.Context) http.Response { - if err := tools.ServiceStop("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "停止PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php81Controller) Restart(ctx http.Context) http.Response { - if err := tools.ServiceRestart("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "重启PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php81Controller) GetConfig(ctx http.Context) http.Response { - config, err := tools.Read("/www/server/php/" + r.version + "/etc/php.ini") - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"配置失败") - } - - return controllers.Success(ctx, config) -} - -func (r *Php81Controller) SaveConfig(ctx http.Context) http.Response { - config := ctx.Request().Input("config") - if err := tools.Write("/www/server/php/"+r.version+"/etc/php.ini", config, 0644); err != nil { - return nil - } - return r.Reload(ctx) -} - -func (r *Php81Controller) Load(ctx http.Context) http.Response { - client := req.C().SetTimeout(10 * time.Second) - resp, err := client.R().Get("http://127.0.0.1/phpfpm_status/" + r.version) - if err != nil || !resp.IsSuccessState() { - facades.Log().Info("获取PHP-" + r.version + "运行状态失败") - return controllers.Error(ctx, http.StatusInternalServerError, "[PHP-"+r.version+"] 获取运行状态失败") - } - - raw := resp.String() - dataKeys := []string{"应用池", "工作模式", "启动时间", "接受连接", "监听队列", "最大监听队列", "监听队列长度", "空闲进程数量", "活动进程数量", "总进程数量", "最大活跃进程数量", "达到进程上限次数", "慢请求"} - regexKeys := []string{"pool", "process manager", "start time", "accepted conn", "listen queue", "max listen queue", "listen queue len", "idle processes", "active processes", "total processes", "max active processes", "max children reached", "slow requests"} - - type Data struct { - Name string `json:"name"` - Value string `json:"value"` - } - data := make([]Data, len(dataKeys)) - for i := range dataKeys { - data[i].Name = dataKeys[i] - - r := regexp.MustCompile(fmt.Sprintf("%s:\\s+(.*)", regexKeys[i])) - match := r.FindStringSubmatch(raw) - - if len(match) > 1 { - data[i].Value = strings.TrimSpace(match[1]) - } - } - - return controllers.Success(ctx, data) -} - -func (r *Php81Controller) ErrorLog(ctx http.Context) http.Response { - log, _ := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/php-fpm.log") - return controllers.Success(ctx, log) -} - -func (r *Php81Controller) SlowLog(ctx http.Context) http.Response { - log, _ := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/slow.log") - return controllers.Success(ctx, log) -} - -func (r *Php81Controller) ClearErrorLog(ctx http.Context) http.Response { - if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/php-fpm.log"); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - - return controllers.Success(ctx, nil) -} - -func (r *Php81Controller) ClearSlowLog(ctx http.Context) http.Response { - if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/slow.log"); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - return controllers.Success(ctx, nil) -} - -func (r *Php81Controller) GetExtensionList(ctx http.Context) http.Response { - extensions := r.GetExtensions() - return controllers.Success(ctx, extensions) -} - -func (r *Php81Controller) InstallExtension(ctx http.Context) http.Response { - slug := ctx.Request().Input("slug") - if len(slug) == 0 { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误") - } - - extensions := r.GetExtensions() - for _, item := range extensions { - if item.Slug == slug { - if item.Installed { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展已安装") - } - - var task models.Task - task.Name = "安装PHP-" + r.version + "扩展-" + item.Name - task.Status = models.TaskStatusWaiting - task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' install ` + r.version + ` >> '/tmp/` + item.Slug + `.log' 2>&1` - task.Log = "/tmp/" + item.Slug + ".log" - if err := facades.Orm().Query().Create(&task); err != nil { - facades.Log().Info("[PHP-" + r.version + "] 创建安装拓展任务失败:" + err.Error()) - return controllers.ErrorSystem(ctx) - } - - r.task.Process(task.ID) - - return controllers.Success(ctx, true) - } - } - - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在") -} - -func (r *Php81Controller) UninstallExtension(ctx http.Context) http.Response { - slug := ctx.Request().Input("slug") - if len(slug) == 0 { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误") - } - - extensions := r.GetExtensions() - for _, item := range extensions { - if item.Slug == slug { - if !item.Installed { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展未安装") - } - - var task models.Task - task.Name = "卸载PHP-" + r.version + "扩展-" + item.Name - task.Status = models.TaskStatusWaiting - task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' uninstall ` + r.version + ` >> '/tmp/` + item.Slug + `.log' 2>&1` - task.Log = "/tmp/" + item.Slug + ".log" - if err := facades.Orm().Query().Create(&task); err != nil { - facades.Log().Info("[PHP-" + r.version + "] 创建卸载拓展任务失败:" + err.Error()) - return controllers.ErrorSystem(ctx) - } - - r.task.Process(task.ID) - - return controllers.Success(ctx, true) - } - } - - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在") -} - -func (r *Php81Controller) GetExtensions() []PHPExtension { - var extensions []PHPExtension - extensions = append(extensions, PHPExtension{ - Name: "OPcache", - Slug: "Zend OPcache", - Description: "OPcache 通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的性能,存储预编译字节码可以省去每次加载和解析 PHP 脚本的开销。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "PhpRedis", - Slug: "redis", - Description: "PhpRedis 是一个用 C 语言编写的 PHP 模块,用来连接并操作 Redis 数据库上的数据。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "ImageMagick", - Slug: "imagick", - Description: "ImageMagick 是一个免费的创建、编辑、合成图片的软件。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "Exif", - Slug: "exif", - Description: "通过 exif 扩展,你可以操作图像元数据。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "pdo_pgsql", - Slug: "pdo_pgsql", - Description: "(需先安装PostgreSQL)pdo_pgsql 是一个驱动程序,它实现了 PHP 数据对象(PDO)接口以启用从 PHP 到 PostgreSQL 数据库的访问。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "ionCube", - Slug: "ionCube Loader", - Description: "ionCube 是一个专业级的 PHP 加密解密工具。", - Installed: false, - }) - - raw, err := tools.Exec("/www/server/php/" + r.version + "/bin/php -m") - if err != nil { - return extensions - } - - rawExtensionList := strings.Split(raw, "\n") - for _, item := range rawExtensionList { - if !strings.Contains(item, "[") && item != "" { - for i := range extensions { - if extensions[i].Slug == item { - extensions[i].Installed = true - } - } - } - } - - return extensions -} diff --git a/app/http/controllers/plugins/php82_controller.go b/app/http/controllers/plugins/php82_controller.go deleted file mode 100644 index a89f2982..00000000 --- a/app/http/controllers/plugins/php82_controller.go +++ /dev/null @@ -1,273 +0,0 @@ -package plugins - -import ( - "fmt" - "regexp" - "strings" - "time" - - "github.com/goravel/framework/contracts/http" - "github.com/goravel/framework/facades" - "github.com/imroc/req/v3" - - "panel/app/http/controllers" - "panel/app/models" - "panel/internal" - "panel/internal/services" - "panel/pkg/tools" -) - -type Php82Controller struct { - setting internal.Setting - task internal.Task - version string -} - -func NewPhp82Controller() *Php82Controller { - return &Php82Controller{ - setting: services.NewSettingImpl(), - task: services.NewTaskImpl(), - version: "82", - } -} - -func (r *Php82Controller) Status(ctx http.Context) http.Response { - status, err := tools.ServiceStatus("php-fpm-" + r.version) - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败") - } - - return controllers.Success(ctx, status) -} - -func (r *Php82Controller) Reload(ctx http.Context) http.Response { - if err := tools.ServiceReload("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "重载PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php82Controller) Start(ctx http.Context) http.Response { - if err := tools.ServiceStart("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "启动PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php82Controller) Stop(ctx http.Context) http.Response { - if err := tools.ServiceStop("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "停止PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php82Controller) Restart(ctx http.Context) http.Response { - if err := tools.ServiceRestart("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "重启PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php82Controller) GetConfig(ctx http.Context) http.Response { - config, err := tools.Read("/www/server/php/" + r.version + "/etc/php.ini") - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"配置失败") - } - - return controllers.Success(ctx, config) -} - -func (r *Php82Controller) SaveConfig(ctx http.Context) http.Response { - config := ctx.Request().Input("config") - if err := tools.Write("/www/server/php/"+r.version+"/etc/php.ini", config, 0644); err != nil { - return nil - } - return r.Reload(ctx) -} - -func (r *Php82Controller) Load(ctx http.Context) http.Response { - client := req.C().SetTimeout(10 * time.Second) - resp, err := client.R().Get("http://127.0.0.1/phpfpm_status/" + r.version) - if err != nil || !resp.IsSuccessState() { - facades.Log().Info("获取PHP-" + r.version + "运行状态失败") - return controllers.Error(ctx, http.StatusInternalServerError, "[PHP-"+r.version+"] 获取运行状态失败") - } - - raw := resp.String() - dataKeys := []string{"应用池", "工作模式", "启动时间", "接受连接", "监听队列", "最大监听队列", "监听队列长度", "空闲进程数量", "活动进程数量", "总进程数量", "最大活跃进程数量", "达到进程上限次数", "慢请求"} - regexKeys := []string{"pool", "process manager", "start time", "accepted conn", "listen queue", "max listen queue", "listen queue len", "idle processes", "active processes", "total processes", "max active processes", "max children reached", "slow requests"} - - type Data struct { - Name string `json:"name"` - Value string `json:"value"` - } - data := make([]Data, len(dataKeys)) - for i := range dataKeys { - data[i].Name = dataKeys[i] - - r := regexp.MustCompile(fmt.Sprintf("%s:\\s+(.*)", regexKeys[i])) - match := r.FindStringSubmatch(raw) - - if len(match) > 1 { - data[i].Value = strings.TrimSpace(match[1]) - } - } - - return controllers.Success(ctx, data) -} - -func (r *Php82Controller) ErrorLog(ctx http.Context) http.Response { - log, _ := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/php-fpm.log") - return controllers.Success(ctx, log) -} - -func (r *Php82Controller) SlowLog(ctx http.Context) http.Response { - log, _ := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/slow.log") - return controllers.Success(ctx, log) -} - -func (r *Php82Controller) ClearErrorLog(ctx http.Context) http.Response { - if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/php-fpm.log"); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - - return controllers.Success(ctx, nil) -} - -func (r *Php82Controller) ClearSlowLog(ctx http.Context) http.Response { - if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/slow.log"); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - return controllers.Success(ctx, nil) -} - -func (r *Php82Controller) GetExtensionList(ctx http.Context) http.Response { - extensions := r.GetExtensions() - return controllers.Success(ctx, extensions) -} - -func (r *Php82Controller) InstallExtension(ctx http.Context) http.Response { - slug := ctx.Request().Input("slug") - if len(slug) == 0 { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误") - } - - extensions := r.GetExtensions() - for _, item := range extensions { - if item.Slug == slug { - if item.Installed { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展已安装") - } - - var task models.Task - task.Name = "安装PHP-" + r.version + "扩展-" + item.Name - task.Status = models.TaskStatusWaiting - task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' install ` + r.version + ` >> '/tmp/` + item.Slug + `.log' 2>&1` - task.Log = "/tmp/" + item.Slug + ".log" - if err := facades.Orm().Query().Create(&task); err != nil { - facades.Log().Info("[PHP-" + r.version + "] 创建安装拓展任务失败:" + err.Error()) - return controllers.ErrorSystem(ctx) - } - - r.task.Process(task.ID) - - return controllers.Success(ctx, true) - } - } - - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在") -} - -func (r *Php82Controller) UninstallExtension(ctx http.Context) http.Response { - slug := ctx.Request().Input("slug") - if len(slug) == 0 { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误") - } - - extensions := r.GetExtensions() - for _, item := range extensions { - if item.Slug == slug { - if !item.Installed { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展未安装") - } - - var task models.Task - task.Name = "卸载PHP-" + r.version + "扩展-" + item.Name - task.Status = models.TaskStatusWaiting - task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' uninstall ` + r.version + ` >> '/tmp/` + item.Slug + `.log' 2>&1` - task.Log = "/tmp/" + item.Slug + ".log" - if err := facades.Orm().Query().Create(&task); err != nil { - facades.Log().Info("[PHP-" + r.version + "] 创建卸载拓展任务失败:" + err.Error()) - return controllers.ErrorSystem(ctx) - } - - r.task.Process(task.ID) - - return controllers.Success(ctx, true) - } - } - - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在") -} - -func (r *Php82Controller) GetExtensions() []PHPExtension { - var extensions []PHPExtension - extensions = append(extensions, PHPExtension{ - Name: "OPcache", - Slug: "Zend OPcache", - Description: "OPcache 通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的性能,存储预编译字节码可以省去每次加载和解析 PHP 脚本的开销。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "PhpRedis", - Slug: "redis", - Description: "PhpRedis 是一个用 C 语言编写的 PHP 模块,用来连接并操作 Redis 数据库上的数据。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "ImageMagick", - Slug: "imagick", - Description: "ImageMagick 是一个免费的创建、编辑、合成图片的软件。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "Exif", - Slug: "exif", - Description: "通过 exif 扩展,你可以操作图像元数据。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "pdo_pgsql", - Slug: "pdo_pgsql", - Description: "(需先安装PostgreSQL)pdo_pgsql 是一个驱动程序,它实现了 PHP 数据对象(PDO)接口以启用从 PHP 到 PostgreSQL 数据库的访问。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "ionCube", - Slug: "ionCube Loader", - Description: "ionCube 是一个专业级的 PHP 加密解密工具。", - Installed: false, - }) - - raw, err := tools.Exec("/www/server/php/" + r.version + "/bin/php -m") - if err != nil { - return extensions - } - - rawExtensionList := strings.Split(raw, "\n") - for _, item := range rawExtensionList { - if !strings.Contains(item, "[") && item != "" { - for i := range extensions { - if extensions[i].Slug == item { - extensions[i].Installed = true - } - } - } - } - - return extensions -} diff --git a/app/http/controllers/plugins/php83_controller.go b/app/http/controllers/plugins/php83_controller.go deleted file mode 100644 index 0e3b9da9..00000000 --- a/app/http/controllers/plugins/php83_controller.go +++ /dev/null @@ -1,267 +0,0 @@ -package plugins - -import ( - "fmt" - "regexp" - "strings" - "time" - - "github.com/goravel/framework/contracts/http" - "github.com/goravel/framework/facades" - "github.com/imroc/req/v3" - - "panel/app/http/controllers" - "panel/app/models" - "panel/internal" - "panel/internal/services" - "panel/pkg/tools" -) - -type Php83Controller struct { - setting internal.Setting - task internal.Task - version string -} - -func NewPhp83Controller() *Php83Controller { - return &Php83Controller{ - setting: services.NewSettingImpl(), - task: services.NewTaskImpl(), - version: "83", - } -} - -func (r *Php83Controller) Status(ctx http.Context) http.Response { - status, err := tools.ServiceStatus("php-fpm-" + r.version) - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败") - } - - return controllers.Success(ctx, status) -} - -func (r *Php83Controller) Reload(ctx http.Context) http.Response { - if err := tools.ServiceReload("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "重载PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php83Controller) Start(ctx http.Context) http.Response { - if err := tools.ServiceStart("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "启动PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php83Controller) Stop(ctx http.Context) http.Response { - if err := tools.ServiceStop("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "停止PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php83Controller) Restart(ctx http.Context) http.Response { - if err := tools.ServiceRestart("php-fpm-" + r.version); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "重启PHP-"+r.version+"失败") - } - - return controllers.Success(ctx, nil) -} - -func (r *Php83Controller) GetConfig(ctx http.Context) http.Response { - config, err := tools.Read("/www/server/php/" + r.version + "/etc/php.ini") - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"配置失败") - } - - return controllers.Success(ctx, config) -} - -func (r *Php83Controller) SaveConfig(ctx http.Context) http.Response { - config := ctx.Request().Input("config") - if err := tools.Write("/www/server/php/"+r.version+"/etc/php.ini", config, 0644); err != nil { - return nil - } - return r.Reload(ctx) -} - -func (r *Php83Controller) Load(ctx http.Context) http.Response { - client := req.C().SetTimeout(10 * time.Second) - resp, err := client.R().Get("http://127.0.0.1/phpfpm_status/" + r.version) - if err != nil || !resp.IsSuccessState() { - facades.Log().Info("获取PHP-" + r.version + "运行状态失败") - return controllers.Error(ctx, http.StatusInternalServerError, "[PHP-"+r.version+"] 获取运行状态失败") - } - - raw := resp.String() - dataKeys := []string{"应用池", "工作模式", "启动时间", "接受连接", "监听队列", "最大监听队列", "监听队列长度", "空闲进程数量", "活动进程数量", "总进程数量", "最大活跃进程数量", "达到进程上限次数", "慢请求"} - regexKeys := []string{"pool", "process manager", "start time", "accepted conn", "listen queue", "max listen queue", "listen queue len", "idle processes", "active processes", "total processes", "max active processes", "max children reached", "slow requests"} - - type Data struct { - Name string `json:"name"` - Value string `json:"value"` - } - data := make([]Data, len(dataKeys)) - for i := range dataKeys { - data[i].Name = dataKeys[i] - - r := regexp.MustCompile(fmt.Sprintf("%s:\\s+(.*)", regexKeys[i])) - match := r.FindStringSubmatch(raw) - - if len(match) > 1 { - data[i].Value = strings.TrimSpace(match[1]) - } - } - - return controllers.Success(ctx, data) -} - -func (r *Php83Controller) ErrorLog(ctx http.Context) http.Response { - log, _ := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/php-fpm.log") - return controllers.Success(ctx, log) -} - -func (r *Php83Controller) SlowLog(ctx http.Context) http.Response { - log, _ := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/slow.log") - return controllers.Success(ctx, log) -} - -func (r *Php83Controller) ClearErrorLog(ctx http.Context) http.Response { - if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/php-fpm.log"); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - - return controllers.Success(ctx, nil) -} - -func (r *Php83Controller) ClearSlowLog(ctx http.Context) http.Response { - if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/slow.log"); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - return controllers.Success(ctx, nil) -} - -func (r *Php83Controller) GetExtensionList(ctx http.Context) http.Response { - extensions := r.GetExtensions() - return controllers.Success(ctx, extensions) -} - -func (r *Php83Controller) InstallExtension(ctx http.Context) http.Response { - slug := ctx.Request().Input("slug") - if len(slug) == 0 { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误") - } - - extensions := r.GetExtensions() - for _, item := range extensions { - if item.Slug == slug { - if item.Installed { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展已安装") - } - - var task models.Task - task.Name = "安装PHP-" + r.version + "扩展-" + item.Name - task.Status = models.TaskStatusWaiting - task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' install ` + r.version + ` >> '/tmp/` + item.Slug + `.log' 2>&1` - task.Log = "/tmp/" + item.Slug + ".log" - if err := facades.Orm().Query().Create(&task); err != nil { - facades.Log().Info("[PHP-" + r.version + "] 创建安装拓展任务失败:" + err.Error()) - return controllers.ErrorSystem(ctx) - } - - r.task.Process(task.ID) - - return controllers.Success(ctx, true) - } - } - - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在") -} - -func (r *Php83Controller) UninstallExtension(ctx http.Context) http.Response { - slug := ctx.Request().Input("slug") - if len(slug) == 0 { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误") - } - - extensions := r.GetExtensions() - for _, item := range extensions { - if item.Slug == slug { - if !item.Installed { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展未安装") - } - - var task models.Task - task.Name = "卸载PHP-" + r.version + "扩展-" + item.Name - task.Status = models.TaskStatusWaiting - task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' uninstall ` + r.version + ` >> '/tmp/` + item.Slug + `.log' 2>&1` - task.Log = "/tmp/" + item.Slug + ".log" - if err := facades.Orm().Query().Create(&task); err != nil { - facades.Log().Info("[PHP-" + r.version + "] 创建卸载拓展任务失败:" + err.Error()) - return controllers.ErrorSystem(ctx) - } - - r.task.Process(task.ID) - - return controllers.Success(ctx, true) - } - } - - return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在") -} - -func (r *Php83Controller) GetExtensions() []PHPExtension { - var extensions []PHPExtension - extensions = append(extensions, PHPExtension{ - Name: "OPcache", - Slug: "Zend OPcache", - Description: "OPcache 通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的性能,存储预编译字节码可以省去每次加载和解析 PHP 脚本的开销。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "PhpRedis", - Slug: "redis", - Description: "PhpRedis 是一个用 C 语言编写的 PHP 模块,用来连接并操作 Redis 数据库上的数据。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "ImageMagick", - Slug: "imagick", - Description: "ImageMagick 是一个免费的创建、编辑、合成图片的软件。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "Exif", - Slug: "exif", - Description: "通过 exif 扩展,你可以操作图像元数据。", - Installed: false, - }) - extensions = append(extensions, PHPExtension{ - Name: "pdo_pgsql", - Slug: "pdo_pgsql", - Description: "(需先安装PostgreSQL)pdo_pgsql 是一个驱动程序,它实现了 PHP 数据对象(PDO)接口以启用从 PHP 到 PostgreSQL 数据库的访问。", - Installed: false, - }) - - raw, err := tools.Exec("/www/server/php/" + r.version + "/bin/php -m") - if err != nil { - return extensions - } - - rawExtensionList := strings.Split(raw, "\n") - for _, item := range rawExtensionList { - if !strings.Contains(item, "[") && item != "" { - for i := range extensions { - if extensions[i].Slug == item { - extensions[i].Installed = true - } - } - } - } - - return extensions -} diff --git a/app/http/controllers/plugins/php_controller.go b/app/http/controllers/plugins/php_controller.go new file mode 100644 index 00000000..ab249ca2 --- /dev/null +++ b/app/http/controllers/plugins/php_controller.go @@ -0,0 +1,149 @@ +package plugins + +import ( + "github.com/goravel/framework/contracts/http" + "panel/app/http/controllers" + "panel/internal" + "panel/internal/services" +) + +type PHPController struct { + service internal.PHP +} + +func NewPHPController(version uint) *PHPController { + return &PHPController{ + service: services.NewPHPImpl(version), + } +} + +func (r *PHPController) Status(ctx http.Context) http.Response { + status, err := r.service.Status() + if err != nil { + return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) + } + + return controllers.Success(ctx, status) +} + +func (r *PHPController) Reload(ctx http.Context) http.Response { + if err := r.service.Reload(); err != nil { + return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) + } + + return controllers.Success(ctx, nil) +} + +func (r *PHPController) Start(ctx http.Context) http.Response { + if err := r.service.Start(); err != nil { + return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) + } + + return controllers.Success(ctx, nil) +} + +func (r *PHPController) Stop(ctx http.Context) http.Response { + if err := r.service.Stop(); err != nil { + return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) + } + + return controllers.Success(ctx, nil) +} + +func (r *PHPController) Restart(ctx http.Context) http.Response { + if err := r.service.Restart(); err != nil { + return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) + } + + return controllers.Success(ctx, nil) +} + +func (r *PHPController) GetConfig(ctx http.Context) http.Response { + config, err := r.service.GetConfig() + if err != nil { + return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) + } + + return controllers.Success(ctx, config) +} + +func (r *PHPController) SaveConfig(ctx http.Context) http.Response { + config := ctx.Request().Input("config") + if err := r.service.SaveConfig(config); err != nil { + return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) + } + + return controllers.Success(ctx, nil) +} + +func (r *PHPController) Load(ctx http.Context) http.Response { + load, err := r.service.Load() + if err != nil { + return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) + } + + return controllers.Success(ctx, load) +} + +func (r *PHPController) ErrorLog(ctx http.Context) http.Response { + log, _ := r.service.GetErrorLog() + return controllers.Success(ctx, log) +} + +func (r *PHPController) SlowLog(ctx http.Context) http.Response { + log, _ := r.service.GetSlowLog() + return controllers.Success(ctx, log) +} + +func (r *PHPController) ClearErrorLog(ctx http.Context) http.Response { + err := r.service.ClearErrorLog() + if err != nil { + return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) + } + + return controllers.Success(ctx, nil) +} + +func (r *PHPController) ClearSlowLog(ctx http.Context) http.Response { + err := r.service.ClearSlowLog() + if err != nil { + return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) + } + + return controllers.Success(ctx, nil) +} + +func (r *PHPController) GetExtensionList(ctx http.Context) http.Response { + extensions, err := r.service.GetExtensions() + if err != nil { + return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) + } + + return controllers.Success(ctx, extensions) +} + +func (r *PHPController) InstallExtension(ctx http.Context) http.Response { + slug := ctx.Request().Input("slug") + if len(slug) == 0 { + return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误") + } + + if err := r.service.InstallExtension(slug); err != nil { + return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) + } + + return controllers.Success(ctx, nil) +} + +func (r *PHPController) UninstallExtension(ctx http.Context) http.Response { + slug := ctx.Request().Input("slug") + if len(slug) == 0 { + return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误") + } + + if err := r.service.UninstallExtension(slug); err != nil { + return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) + } + + return controllers.Success(ctx, nil) +} diff --git a/internal/constants.go b/internal/constants.go new file mode 100644 index 00000000..afaee5ef --- /dev/null +++ b/internal/constants.go @@ -0,0 +1,11 @@ +package internal + +type NV struct { + Name string `json:"name"` + Value string `json:"value"` +} + +type KV struct { + Key string `json:"key"` + Value string `json:"value"` +} diff --git a/internal/php.go b/internal/php.go new file mode 100644 index 00000000..be87f99b --- /dev/null +++ b/internal/php.go @@ -0,0 +1,28 @@ +package internal + +type PHPExtension struct { + Name string `json:"name"` + Slug string `json:"slug"` + Description string `json:"description"` + Installed bool `json:"installed"` +} + +type PHP interface { + Status() (bool, error) + Reload() error + Start() error + Stop() error + Restart() error + GetConfig() (string, error) + SaveConfig(config string) error + GetFPMConfig() (string, error) + SaveFPMConfig(config string) error + Load() ([]NV, error) + GetErrorLog() (string, error) + GetSlowLog() (string, error) + ClearErrorLog() error + ClearSlowLog() error + GetExtensions() ([]PHPExtension, error) + InstallExtension(slug string) error + UninstallExtension(slug string) error +} diff --git a/internal/plugin_list.go b/internal/plugin_list.go new file mode 100644 index 00000000..b577424b --- /dev/null +++ b/internal/plugin_list.go @@ -0,0 +1,218 @@ +// Package internal 插件定义文件 +package internal + +var PluginOpenResty = PanelPlugin{ + Name: "OpenResty", + Description: "OpenResty® 是一款基于 NGINX 和 LuaJIT 的 Web 平台。", + Slug: "openresty", + Version: "1.25.3.1", + Requires: []string{}, + Excludes: []string{}, + Install: "bash /www/panel/scripts/openresty/install.sh", + Uninstall: "bash /www/panel/scripts/openresty/uninstall.sh", + Update: "bash /www/panel/scripts/openresty/install.sh", +} + +var PluginMySQL57 = PanelPlugin{ + Name: "MySQL-5.7", + Description: "MySQL 是最流行的关系型数据库管理系统之一,Oracle 旗下产品。(已停止维护,不建议使用!预计 2025 年 12 月移除)", + Slug: "mysql57", + Version: "5.7.44", + Requires: []string{}, + Excludes: []string{"mysql80"}, + Install: `bash /www/panel/scripts/mysql/install.sh 57`, + Uninstall: `bash /www/panel/scripts/mysql/uninstall.sh 57`, + Update: `bash /www/panel/scripts/mysql/update.sh 57`, +} + +var PluginMySQL80 = PanelPlugin{ + Name: "MySQL-8.0", + Description: "MySQL 是最流行的关系型数据库管理系统之一,Oracle 旗下产品。(建议内存 > 2G 安装)", + Slug: "mysql80", + Version: "8.0.36", + Requires: []string{}, + Excludes: []string{"mysql57"}, + Install: `bash /www/panel/scripts/mysql/install.sh 80`, + Uninstall: `bash /www/panel/scripts/mysql/uninstall.sh 80`, + Update: `bash /www/panel/scripts/mysql/update.sh 80`, +} + +var PluginPostgreSQL15 = PanelPlugin{ + Name: "PostgreSQL-15", + Description: "PostgreSQL 是世界上最先进的开源关系数据库,在类似 BSD 与 MIT 许可的 PostgreSQL 许可下发行。", + Slug: "postgresql15", + Version: "15.6", + Requires: []string{}, + Excludes: []string{"postgresql16"}, + Install: `bash /www/panel/scripts/postgresql/install.sh 15`, + Uninstall: `bash /www/panel/scripts/postgresql/uninstall.sh 15`, + Update: `bash /www/panel/scripts/postgresql/update.sh 15`, +} + +var PluginPostgreSQL16 = PanelPlugin{ + Name: "PostgreSQL-16", + Description: "PostgreSQL 是世界上最先进的开源关系数据库,在类似 BSD 与 MIT 许可的 PostgreSQL 许可下发行。", + Slug: "postgresql16", + Version: "16.2", + Requires: []string{}, + Excludes: []string{"postgresql15"}, + Install: `bash /www/panel/scripts/postgresql/install.sh 16`, + Uninstall: `bash /www/panel/scripts/postgresql/uninstall.sh 16`, + Update: `bash /www/panel/scripts/postgresql/update.sh 16`, +} + +var PluginPHP74 = PanelPlugin{ + Name: "PHP-7.4", + Description: "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。(已停止维护,不建议使用!预计 2024 年 12 月移除)", + Slug: "php74", + Version: "7.4.33", + Requires: []string{}, + Excludes: []string{}, + Install: `bash /www/panel/scripts/php/install.sh 74`, + Uninstall: `bash /www/panel/scripts/php/uninstall.sh 74`, + Update: `bash /www/panel/scripts/php/install.sh 74`, +} + +var PluginPHP80 = PanelPlugin{ + Name: "PHP-8.0", + Description: "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。(已停止维护,不建议使用!预计 2025 年 12 月移除)", + Slug: "php80", + Version: "8.0.30", + Requires: []string{}, + Excludes: []string{}, + Install: `bash /www/panel/scripts/php/install.sh 80`, + Uninstall: `bash /www/panel/scripts/php/uninstall.sh 80`, + Update: `bash /www/panel/scripts/php/install.sh 80`, +} + +var PluginPHP81 = PanelPlugin{ + Name: "PHP-8.1", + Description: "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。", + Slug: "php81", + Version: "8.1.27", + Requires: []string{}, + Excludes: []string{}, + Install: `bash /www/panel/scripts/php/install.sh 81`, + Uninstall: `bash /www/panel/scripts/php/uninstall.sh 81`, + Update: `bash /www/panel/scripts/php/install.sh 81`, +} + +var PluginPHP82 = PanelPlugin{ + Name: "PHP-8.2", + Description: "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。", + Slug: "php82", + Version: "8.2.16", + Requires: []string{}, + Excludes: []string{}, + Install: `bash /www/panel/scripts/php/install.sh 82`, + Uninstall: `bash /www/panel/scripts/php/uninstall.sh 82`, + Update: `bash /www/panel/scripts/php/install.sh 82`, +} + +var PluginPHP83 = PanelPlugin{ + Name: "PHP-8.3", + Description: "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。", + Slug: "php83", + Version: "8.3.3", + Requires: []string{}, + Excludes: []string{}, + Install: `bash /www/panel/scripts/php/install.sh 83`, + Uninstall: `bash /www/panel/scripts/php/uninstall.sh 83`, + Update: `bash /www/panel/scripts/php/install.sh 83`, +} + +var PluginPHPMyAdmin = PanelPlugin{ + Name: "phpMyAdmin", + Description: "phpMyAdmin 是一个以 PHP 为基础,以 Web-Base 方式架构在网站主机上的 MySQL 数据库管理工具。", + Slug: "phpmyadmin", + Version: "5.2.1", + Requires: []string{}, + Excludes: []string{}, + Install: `bash /www/panel/scripts/phpmyadmin/install.sh`, + Uninstall: `bash /www/panel/scripts/phpmyadmin/uninstall.sh`, + Update: `bash /www/panel/scripts/phpmyadmin/uninstall.sh && bash /www/panel/scripts/phpmyadmin/install.sh`, +} + +var PluginPureFTPd = PanelPlugin{ + Name: "Pure-FTPd", + Description: "Pure-Ftpd 是一个快速、高效、轻便、安全的 FTP 服务器,它以安全和配置简单为设计目标,支持虚拟主机,IPV6,PAM 等功能。", + Slug: "pureftpd", + Version: "1.0.50", + Requires: []string{}, + Excludes: []string{}, + Install: `bash /www/panel/scripts/pureftpd/install.sh`, + Uninstall: `bash /www/panel/scripts/pureftpd/uninstall.sh`, + Update: `bash /www/panel/scripts/pureftpd/update.sh`, +} + +var PluginRedis = PanelPlugin{ + Name: "Redis", + Description: "Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。", + Slug: "redis", + Version: "7.2.4", + Requires: []string{}, + Excludes: []string{}, + Install: `bash /www/panel/scripts/redis/install.sh`, + Uninstall: `bash /www/panel/scripts/redis/uninstall.sh`, + Update: `bash /www/panel/scripts/redis/update.sh`, +} + +var PluginS3fs = PanelPlugin{ + Name: "S3fs", + Description: "S3fs 通过 FUSE 挂载兼容 S3 标准的存储桶,例如 Amazon S3、阿里云 OSS、腾讯云 COS、七牛云 Kodo 等。", + Slug: "s3fs", + Version: "1.9", + Requires: []string{}, + Excludes: []string{}, + Install: `bash /www/panel/scripts/s3fs/install.sh`, + Uninstall: `bash /www/panel/scripts/s3fs/uninstall.sh`, + Update: `bash /www/panel/scripts/s3fs/update.sh`, +} + +var PluginRsync = PanelPlugin{ + Name: "Rsync", + Description: "Rsync 是一款提供快速增量文件传输的开源工具。", + Slug: "rsync", + Version: "3.2.7", + Requires: []string{}, + Excludes: []string{}, + Install: `bash /www/panel/scripts/rsync/install.sh`, + Uninstall: `bash /www/panel/scripts/rsync/uninstall.sh`, + Update: `bash /www/panel/scripts/rsync/install.sh`, +} + +var PluginSupervisor = PanelPlugin{ + Name: "Supervisor", + Description: "Supervisor 是一个客户端/服务器系统,允许用户监视和控制类 UNIX 操作系统上的多个进程。", + Slug: "supervisor", + Version: "4.2.5", + Requires: []string{}, + Excludes: []string{}, + Install: `bash /www/panel/scripts/supervisor/install.sh`, + Uninstall: `bash /www/panel/scripts/supervisor/uninstall.sh`, + Update: `bash /www/panel/scripts/supervisor/update.sh`, +} + +var PluginFail2ban = PanelPlugin{ + Name: "Fail2ban", + Description: "Fail2ban 扫描系统日志文件并从中找出多次尝试失败的IP地址,将该IP地址加入防火墙的拒绝访问列表中。", + Slug: "fail2ban", + Version: "1.0.0", + Requires: []string{}, + Excludes: []string{}, + Install: `bash /www/panel/scripts/fail2ban/install.sh`, + Uninstall: `bash /www/panel/scripts/fail2ban/uninstall.sh`, + Update: `bash /www/panel/scripts/fail2ban/update.sh`, +} + +var PluginToolBox = PanelPlugin{ + Name: "系统工具箱", + Description: "可视化调整一些常用的配置项,如 DNS、SWAP、时区等", + Slug: "toolbox", + Version: "1.0.0", + Requires: []string{}, + Excludes: []string{}, + Install: `panel writePlugin toolbox 1.0`, + Uninstall: `panel deletePlugin toolbox`, + Update: `panel writePlugin toolbox 1.0`, +} diff --git a/internal/plugins/fail2ban/fail2ban.go b/internal/plugins/fail2ban/fail2ban.go deleted file mode 100644 index 2f6fbd4f..00000000 --- a/internal/plugins/fail2ban/fail2ban.go +++ /dev/null @@ -1,13 +0,0 @@ -package fail2ban - -var ( - Name = "Fail2ban" - Description = "Fail2ban 扫描系统日志文件并从中找出多次尝试失败的IP地址,将该IP地址加入防火墙的拒绝访问列表中。" - Slug = "fail2ban" - Version = "1.0.0" - Requires = []string{} - Excludes = []string{} - Install = `bash /www/panel/scripts/fail2ban/install.sh` - Uninstall = `bash /www/panel/scripts/fail2ban/uninstall.sh` - Update = `bash /www/panel/scripts/fail2ban/update.sh` -) diff --git a/internal/plugins/mysql57/mysql57.go b/internal/plugins/mysql57/mysql57.go deleted file mode 100644 index 9e1fa8c5..00000000 --- a/internal/plugins/mysql57/mysql57.go +++ /dev/null @@ -1,13 +0,0 @@ -package mysql57 - -var ( - Name = "MySQL-5.7" - Description = "MySQL 是最流行的关系型数据库管理系统之一,Oracle 旗下产品。(已停止维护,不建议使用!预计 2025 年 12 月移除)" - Slug = "mysql57" - Version = "5.7.44" - Requires = []string{} - Excludes = []string{"mysql80"} - Install = `bash /www/panel/scripts/mysql/install.sh 57` - Uninstall = `bash /www/panel/scripts/mysql/uninstall.sh 57` - Update = `bash /www/panel/scripts/mysql/update.sh 57` -) diff --git a/internal/plugins/mysql80/mysql80.go b/internal/plugins/mysql80/mysql80.go deleted file mode 100644 index 9c3fae4c..00000000 --- a/internal/plugins/mysql80/mysql80.go +++ /dev/null @@ -1,13 +0,0 @@ -package mysql80 - -var ( - Name = "MySQL-8.0" - Description = "MySQL 是最流行的关系型数据库管理系统之一,Oracle 旗下产品。(建议内存 > 2G 安装)" - Slug = "mysql80" - Version = "8.0.36" - Requires = []string{} - Excludes = []string{"mysql57"} - Install = `bash /www/panel/scripts/mysql/install.sh 80` - Uninstall = `bash /www/panel/scripts/mysql/uninstall.sh 80` - Update = `bash /www/panel/scripts/mysql/update.sh 80` -) diff --git a/internal/plugins/openresty/openresty.go b/internal/plugins/openresty/openresty.go deleted file mode 100644 index e83ae92d..00000000 --- a/internal/plugins/openresty/openresty.go +++ /dev/null @@ -1,13 +0,0 @@ -package openresty - -var ( - Name = "OpenResty" - Description = "OpenResty® 是一款基于 NGINX 和 LuaJIT 的 Web 平台。" - Slug = "openresty" - Version = "1.25.3.1" - Requires = []string{} - Excludes = []string{} - Install = "bash /www/panel/scripts/openresty/install.sh" - Uninstall = "bash /www/panel/scripts/openresty/uninstall.sh" - Update = "bash /www/panel/scripts/openresty/install.sh" -) diff --git a/internal/plugins/php74/php74.go b/internal/plugins/php74/php74.go deleted file mode 100644 index 7be11a4b..00000000 --- a/internal/plugins/php74/php74.go +++ /dev/null @@ -1,13 +0,0 @@ -package php74 - -var ( - Name = "PHP-7.4" - Description = "PHP 是世界上最好的语言!(已停止维护,不建议使用!预计 2024 年 12 月移除)" - Slug = "php74" - Version = "7.4.33" - Requires = []string{} - Excludes = []string{} - Install = `bash /www/panel/scripts/php/install.sh 74` - Uninstall = `bash /www/panel/scripts/php/uninstall.sh 74` - Update = `bash /www/panel/scripts/php/install.sh 74` -) diff --git a/internal/plugins/php80/php80.go b/internal/plugins/php80/php80.go deleted file mode 100644 index 42cb1e32..00000000 --- a/internal/plugins/php80/php80.go +++ /dev/null @@ -1,13 +0,0 @@ -package php80 - -var ( - Name = "PHP-8.0" - Description = "PHP 是世界上最好的语言!(已停止维护,不建议使用!预计 2025 年 12 月移除)" - Slug = "php80" - Version = "8.0.30" - Requires = []string{} - Excludes = []string{} - Install = `bash /www/panel/scripts/php/install.sh 80` - Uninstall = `bash /www/panel/scripts/php/uninstall.sh 80` - Update = `bash /www/panel/scripts/php/install.sh 80` -) diff --git a/internal/plugins/php81/php81.go b/internal/plugins/php81/php81.go deleted file mode 100644 index cb9a1cc2..00000000 --- a/internal/plugins/php81/php81.go +++ /dev/null @@ -1,13 +0,0 @@ -package php81 - -var ( - Name = "PHP-8.1" - Description = "PHP 是世界上最好的语言!" - Slug = "php81" - Version = "8.1.27" - Requires = []string{} - Excludes = []string{} - Install = `bash /www/panel/scripts/php/install.sh 81` - Uninstall = `bash /www/panel/scripts/php/uninstall.sh 81` - Update = `bash /www/panel/scripts/php/install.sh 81` -) diff --git a/internal/plugins/php82/php82.go b/internal/plugins/php82/php82.go deleted file mode 100644 index 7896d6d5..00000000 --- a/internal/plugins/php82/php82.go +++ /dev/null @@ -1,13 +0,0 @@ -package php82 - -var ( - Name = "PHP-8.2" - Description = "PHP 是世界上最好的语言!" - Slug = "php82" - Version = "8.2.16" - Requires = []string{} - Excludes = []string{} - Install = `bash /www/panel/scripts/php/install.sh 82` - Uninstall = `bash /www/panel/scripts/php/uninstall.sh 82` - Update = `bash /www/panel/scripts/php/install.sh 82` -) diff --git a/internal/plugins/php83/php83.go b/internal/plugins/php83/php83.go deleted file mode 100644 index fed85990..00000000 --- a/internal/plugins/php83/php83.go +++ /dev/null @@ -1,13 +0,0 @@ -package php83 - -var ( - Name = "PHP-8.3" - Description = "PHP 是世界上最好的语言!" - Slug = "php83" - Version = "8.3.3" - Requires = []string{} - Excludes = []string{} - Install = `bash /www/panel/scripts/php/install.sh 83` - Uninstall = `bash /www/panel/scripts/php/uninstall.sh 83` - Update = `bash /www/panel/scripts/php/install.sh 83` -) diff --git a/internal/plugins/phpmyadmin/phpmyadmin.go b/internal/plugins/phpmyadmin/phpmyadmin.go deleted file mode 100644 index fb07a9ce..00000000 --- a/internal/plugins/phpmyadmin/phpmyadmin.go +++ /dev/null @@ -1,13 +0,0 @@ -package phpmyadmin - -var ( - Name = "phpMyAdmin" - Description = "phpMyAdmin 是一个以 PHP 为基础,以 Web-Base 方式架构在网站主机上的 MySQL 数据库管理工具。" - Slug = "phpmyadmin" - Version = "5.2.1" - Requires = []string{} - Excludes = []string{} - Install = `bash /www/panel/scripts/phpmyadmin/install.sh` - Uninstall = `bash /www/panel/scripts/phpmyadmin/uninstall.sh` - Update = `bash /www/panel/scripts/phpmyadmin/uninstall.sh && bash /www/panel/scripts/phpmyadmin/install.sh` -) diff --git a/internal/plugins/postgresql15/postgresql15.go b/internal/plugins/postgresql15/postgresql15.go deleted file mode 100644 index 28f6efc4..00000000 --- a/internal/plugins/postgresql15/postgresql15.go +++ /dev/null @@ -1,13 +0,0 @@ -package postgresql15 - -var ( - Name = "PostgreSQL-15" - Description = "PostgreSQL 是世界上最先进的开源关系数据库,在类似 BSD 与 MIT 许可的 PostgreSQL 许可下发行。" - Slug = "postgresql15" - Version = "15.6" - Requires = []string{} - Excludes = []string{"postgresql16"} - Install = `bash /www/panel/scripts/postgresql/install.sh 15` - Uninstall = `bash /www/panel/scripts/postgresql/uninstall.sh 15` - Update = `bash /www/panel/scripts/postgresql/update.sh 15` -) diff --git a/internal/plugins/postgresql16/postgresql16.go b/internal/plugins/postgresql16/postgresql16.go deleted file mode 100644 index 44a0ce69..00000000 --- a/internal/plugins/postgresql16/postgresql16.go +++ /dev/null @@ -1,13 +0,0 @@ -package postgresql16 - -var ( - Name = "PostgreSQL-16" - Description = "PostgreSQL 是世界上最先进的开源关系数据库,在类似 BSD 与 MIT 许可的 PostgreSQL 许可下发行。" - Slug = "postgresql16" - Version = "16.2" - Requires = []string{} - Excludes = []string{"postgresql15"} - Install = `bash /www/panel/scripts/postgresql/install.sh 16` - Uninstall = `bash /www/panel/scripts/postgresql/uninstall.sh 16` - Update = `bash /www/panel/scripts/postgresql/update.sh 16` -) diff --git a/internal/plugins/pureftpd/pureftpd.go b/internal/plugins/pureftpd/pureftpd.go deleted file mode 100644 index 614e59c6..00000000 --- a/internal/plugins/pureftpd/pureftpd.go +++ /dev/null @@ -1,13 +0,0 @@ -package pureftpd - -var ( - Name = "Pure-FTPd" - Description = "Pure-Ftpd 是一个快速、高效、轻便、安全的 FTP 服务器,它以安全和配置简单为设计目标,支持虚拟主机,IPV6,PAM 等功能。" - Slug = "pureftpd" - Version = "1.0.50" - Requires = []string{} - Excludes = []string{} - Install = `bash /www/panel/scripts/pureftpd/install.sh` - Uninstall = `bash /www/panel/scripts/pureftpd/uninstall.sh` - Update = `bash /www/panel/scripts/pureftpd/update.sh` -) diff --git a/internal/plugins/redis/redis.go b/internal/plugins/redis/redis.go deleted file mode 100644 index 2f82c542..00000000 --- a/internal/plugins/redis/redis.go +++ /dev/null @@ -1,13 +0,0 @@ -package redis - -var ( - Name = "Redis" - Description = "Redis 是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。" - Slug = "redis" - Version = "7.2.4" - Requires = []string{} - Excludes = []string{} - Install = `bash /www/panel/scripts/redis/install.sh` - Uninstall = `bash /www/panel/scripts/redis/uninstall.sh` - Update = `bash /www/panel/scripts/redis/update.sh` -) diff --git a/internal/plugins/rsync/rsync.go b/internal/plugins/rsync/rsync.go deleted file mode 100644 index 5590b462..00000000 --- a/internal/plugins/rsync/rsync.go +++ /dev/null @@ -1,13 +0,0 @@ -package rsync - -var ( - Name = "Rsync" - Description = "Rsync 是一款提供快速增量文件传输的开源工具。" - Slug = "rsync" - Version = "3.2.7" - Requires = []string{} - Excludes = []string{} - Install = `bash /www/panel/scripts/rsync/install.sh` - Uninstall = `bash /www/panel/scripts/rsync/uninstall.sh` - Update = `bash /www/panel/scripts/rsync/install.sh` -) diff --git a/internal/plugins/s3fs/s3fs.go b/internal/plugins/s3fs/s3fs.go deleted file mode 100644 index cfc08ac4..00000000 --- a/internal/plugins/s3fs/s3fs.go +++ /dev/null @@ -1,13 +0,0 @@ -package s3fs - -var ( - Name = "S3fs" - Description = "S3fs 通过 FUSE 挂载兼容 S3 标准的存储桶,例如Amazon S3、阿里云OSS、腾讯云COS、七牛云Kodo等。" - Slug = "s3fs" - Version = "1.9" - Requires = []string{} - Excludes = []string{} - Install = `bash /www/panel/scripts/s3fs/install.sh` - Uninstall = `bash /www/panel/scripts/s3fs/uninstall.sh` - Update = `bash /www/panel/scripts/s3fs/update.sh` -) diff --git a/internal/plugins/supervisor/supervisor.go b/internal/plugins/supervisor/supervisor.go deleted file mode 100644 index 3cbf646c..00000000 --- a/internal/plugins/supervisor/supervisor.go +++ /dev/null @@ -1,13 +0,0 @@ -package supervisor - -var ( - Name = "Supervisor" - Description = "Supervisor 是一个客户端/服务器系统,允许用户监视和控制类 UNIX 操作系统上的多个进程。" - Slug = "supervisor" - Version = "4.2.5" - Requires = []string{} - Excludes = []string{} - Install = `bash /www/panel/scripts/supervisor/install.sh` - Uninstall = `bash /www/panel/scripts/supervisor/uninstall.sh` - Update = `bash /www/panel/scripts/supervisor/update.sh` -) diff --git a/internal/plugins/toolbox/toolbox.go b/internal/plugins/toolbox/toolbox.go deleted file mode 100644 index d717fd44..00000000 --- a/internal/plugins/toolbox/toolbox.go +++ /dev/null @@ -1,13 +0,0 @@ -package toolbox - -var ( - Name = "系统工具箱" - Description = "可视化调整一些常用的配置项,如 DNS、SWAP、时区 等" - Slug = "toolbox" - Version = "1.0" - Requires = []string{} - Excludes = []string{} - Install = `panel writePlugin toolbox 1.0` - Uninstall = `panel deletePlugin toolbox` - Update = `panel writePlugin toolbox 1.0` -) diff --git a/internal/services/php.go b/internal/services/php.go new file mode 100644 index 00000000..8a4ba54f --- /dev/null +++ b/internal/services/php.go @@ -0,0 +1,368 @@ +package services + +import ( + "errors" + "fmt" + "regexp" + "slices" + "strings" + "time" + + "github.com/goravel/framework/facades" + "github.com/imroc/req/v3" + "github.com/spf13/cast" + + "panel/app/models" + "panel/internal" + "panel/pkg/tools" +) + +type PHPImpl struct { + version string +} + +func NewPHPImpl(version uint) *PHPImpl { + return &PHPImpl{ + version: cast.ToString(version), + } +} + +func (r *PHPImpl) Status() (bool, error) { + return tools.ServiceStatus("php-fpm-" + r.version) +} + +func (r *PHPImpl) Reload() error { + return tools.ServiceReload("php-fpm-" + r.version) +} + +func (r *PHPImpl) Start() error { + return tools.ServiceStart("php-fpm-" + r.version) +} + +func (r *PHPImpl) Stop() error { + return tools.ServiceStop("php-fpm-" + r.version) +} + +func (r *PHPImpl) Restart() error { + return tools.ServiceRestart("php-fpm-" + r.version) +} + +func (r *PHPImpl) GetConfig() (string, error) { + return tools.Read("/www/server/php/" + r.version + "/etc/php.ini") +} + +func (r *PHPImpl) SaveConfig(config string) error { + if err := tools.Write("/www/server/php/"+r.version+"/etc/php.ini", config, 0644); err != nil { + return err + } + + return r.Reload() +} + +func (r *PHPImpl) GetFPMConfig() (string, error) { + return tools.Read("/www/server/php/" + r.version + "/etc/php-fpm.conf") +} + +func (r *PHPImpl) SaveFPMConfig(config string) error { + if err := tools.Write("/www/server/php/"+r.version+"/etc/php-fpm.conf", config, 0644); err != nil { + return err + } + + return r.Reload() +} + +func (r *PHPImpl) Load() ([]internal.NV, error) { + client := req.C().SetTimeout(10 * time.Second) + resp, err := client.R().Get("http://127.0.0.1/phpfpm_status/" + r.version) + if err != nil || !resp.IsSuccessState() { + return nil, errors.New("获取 PHP-" + r.version + " 运行状态失败") + } + + raw := resp.String() + dataKeys := []string{"应用池", "工作模式", "启动时间", "接受连接", "监听队列", "最大监听队列", "监听队列长度", "空闲进程数量", "活动进程数量", "总进程数量", "最大活跃进程数量", "达到进程上限次数", "慢请求"} + regexKeys := []string{"pool", "process manager", "start time", "accepted conn", "listen queue", "max listen queue", "listen queue len", "idle processes", "active processes", "total processes", "max active processes", "max children reached", "slow requests"} + + data := make([]internal.NV, len(dataKeys)) + for i := range dataKeys { + data[i].Name = dataKeys[i] + + r := regexp.MustCompile(fmt.Sprintf("%s:\\s+(.*)", regexKeys[i])) + match := r.FindStringSubmatch(raw) + + if len(match) > 1 { + data[i].Value = strings.TrimSpace(match[1]) + } + } + + return data, nil +} + +func (r *PHPImpl) GetErrorLog() (string, error) { + return tools.Exec("tail -n 500 /www/server/php/" + r.version + "/var/log/php-fpm.log") +} + +func (r *PHPImpl) GetSlowLog() (string, error) { + return tools.Exec("tail -n 500 /www/server/php/" + r.version + "/var/log/slow.log") +} + +func (r *PHPImpl) ClearErrorLog() error { + if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/php-fpm.log"); err != nil { + return errors.New(out) + } + + return r.Reload() +} + +func (r *PHPImpl) ClearSlowLog() error { + if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/slow.log"); err != nil { + return errors.New(out) + } + + return nil +} + +func (r *PHPImpl) GetExtensions() ([]internal.PHPExtension, error) { + extensions := []internal.PHPExtension{ + { + Name: "fileinfo", + Slug: "fileinfo", + Description: "Fileinfo 是一个用于识别文件类型的库。", + Installed: false, + }, + { + Name: "OPcache", + Slug: "Zend OPcache", + Description: "OPcache 通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的性能,存储预编译字节码可以省去每次加载和解析 PHP 脚本的开销。", + Installed: false, + }, + { + Name: "PhpRedis", + Slug: "redis", + Description: "PhpRedis 是一个用 C 语言编写的 PHP 模块,用来连接并操作 Redis 数据库上的数据。", + Installed: false, + }, + { + Name: "ImageMagick", + Slug: "imagick", + Description: "ImageMagick 是一个免费的创建、编辑、合成图片的软件。", + Installed: false, + }, + { + Name: "exif", + Slug: "exif", + Description: "通过 exif 扩展,你可以操作图像元数据。", + Installed: false, + }, + { + Name: "pdo_pgsql", + Slug: "pdo_pgsql", + Description: "(需先安装PostgreSQL)pdo_pgsql 是一个驱动程序,它实现了 PHP 数据对象(PDO)接口以启用从 PHP 到 PostgreSQL 数据库的访问。", + Installed: false, + }, + { + Name: "imap", + Slug: "imap", + Description: "IMAP 扩展允许 PHP 读取、搜索、删除、下载和管理邮件。", + Installed: false, + }, + { + Name: "zip", + Slug: "zip", + Description: "Zip 是一个用于处理 ZIP 文件的库。", + Installed: false, + }, + { + Name: "bz2", + Slug: "bz2", + Description: "Bzip2 是一个用于压缩和解压缩文件的库。", + Installed: false, + }, + { + Name: "readline", + Slug: "readline", + Description: "Readline 是一个库,它提供了一种用于处理文本的接口。", + Installed: false, + }, + { + Name: "snmp", + Slug: "snmp", + Description: "SNMP 是一种用于网络管理的协议。", + Installed: false, + }, + { + Name: "ldap", + Slug: "ldap", + Description: "LDAP 是一种用于访问目录服务的协议。", + }, + { + Name: "enchant", + Slug: "enchant", + Description: "Enchant 是一个拼写检查库。", + Installed: false, + }, + { + Name: "pspell", + Slug: "pspell", + Description: "Pspell 是一个拼写检查库。", + Installed: false, + }, + { + Name: "calendar", + Slug: "calendar", + Description: "Calendar 是一个用于处理日期的库。", + Installed: false, + }, + { + Name: "gmp", + Slug: "gmp", + Description: "GMP 是一个用于处理大整数的库。", + Installed: false, + }, + { + Name: "sysvmsg", + Slug: "sysvmsg", + Description: "Sysvmsg 是一个用于处理 System V 消息队列的库。", + Installed: false, + }, + { + Name: "sysvsem", + Slug: "sysvsem", + Description: "Sysvsem 是一个用于处理 System V 信号量的库。", + }, + { + Name: "sysvshm", + Slug: "sysvshm", + Description: "Sysvshm 是一个用于处理 System V 共享内存的库。", + Installed: false, + }, + { + Name: "xsl", + Slug: "xsl", + Description: "XSL 是一个用于处理 XML 文档的库。", + Installed: false, + }, + { + Name: "intl", + Slug: "intl", + Description: "Intl 是一个用于处理国际化和本地化的库。", + Installed: false, + }, + { + Name: "gettext", + Slug: "gettext", + Description: "Gettext 是一个用于处理多语言的库。", + Installed: false, + }, + /*{ + Name: "igbinary", + Slug: "igbinary", + Description: "Igbinary 是一个用于序列化和反序列化数据的库。", + Installed: false, + }, + { + Name: "swoole", + Slug: "swoole", + Description: "Swoole 是一个用于构建高性能的异步并发服务器的 PHP 扩展。", + Installed: false, + }, + { + Name: "swow", + Slug: "swow", + Description: "Swow 是一个用于构建高性能的异步并发服务器的 PHP 扩展。", + Installed: false, + },*/ + } + + if cast.ToUint(r.version) < 83 { + extensions = append(extensions, internal.PHPExtension{ + Name: "ionCube", + Slug: "ionCube Loader", + Description: "ionCube 是一个专业级的 PHP 加密解密工具。", + Installed: false, + }) + } + + raw, err := tools.Exec("/www/server/php/" + r.version + "/bin/php -m") + if err != nil { + return extensions, err + } + + extensionMap := make(map[string]*internal.PHPExtension) + for i := range extensions { + extensionMap[extensions[i].Slug] = &extensions[i] + } + + rawExtensionList := strings.Split(raw, "\n") + for _, item := range rawExtensionList { + if ext, exists := extensionMap[item]; exists && !strings.Contains(item, "[") && item != "" { + ext.Installed = true + } + } + + return extensions, nil +} + +func (r *PHPImpl) InstallExtension(slug string) error { + if !r.checkExtension(slug) { + return errors.New("扩展不存在") + } + + shell := fmt.Sprintf(`bash '/www/panel/scripts/php_extensions/%s.sh' install %s >> '/tmp/%s.log' 2>&1`, slug, r.version, slug) + + officials := []string{"fileinfo", "exif", "imap", "pdo_pgsql", "zip", "bz2", "readline", "snmp", "ldap", "enchant", "pspell", "calendar", "gmp", "sysvmsg", "sysvsem", "sysvshm", "xsl", "intl", "gettext"} + if slices.Contains(officials, slug) { + shell = fmt.Sprintf(`bash '/www/panel/scripts/php_extensions/official.sh' install '%s' '%s' >> '/tmp/%s.log' 2>&1`, r.version, slug, slug) + } + + var task models.Task + task.Name = "安装PHP-" + r.version + "扩展-" + slug + task.Status = models.TaskStatusWaiting + task.Shell = shell + task.Log = "/tmp/" + slug + ".log" + if err := facades.Orm().Query().Create(&task); err != nil { + return err + } + + NewTaskImpl().Process(task.ID) + return nil +} + +func (r *PHPImpl) UninstallExtension(slug string) error { + if !r.checkExtension(slug) { + return errors.New("扩展不存在") + } + + shell := fmt.Sprintf(`bash '/www/panel/scripts/php_extensions/%s.sh' uninstall %s >> '/tmp/%s.log' 2>&1`, slug, r.version, slug) + + officials := []string{"fileinfo", "exif", "imap", "pdo_pgsql", "zip", "bz2", "readline", "snmp", "ldap", "enchant", "pspell", "calendar", "gmp", "sysvmsg", "sysvsem", "sysvshm", "xsl", "intl", "gettext"} + if slices.Contains(officials, slug) { + shell = fmt.Sprintf(`bash '/www/panel/scripts/php_extensions/official.sh' uninstall '%s' '%s' >> '/tmp/%s.log' 2>&1`, r.version, slug, slug) + } + + var task models.Task + task.Name = "卸载PHP-" + r.version + "扩展-" + slug + task.Status = models.TaskStatusWaiting + task.Shell = shell + task.Log = "/tmp/" + slug + ".log" + if err := facades.Orm().Query().Create(&task); err != nil { + return err + } + + NewTaskImpl().Process(task.ID) + return nil +} + +func (r *PHPImpl) checkExtension(slug string) bool { + extensions, err := r.GetExtensions() + if err != nil { + return false + } + + for _, item := range extensions { + if item.Slug == slug { + return true + } + } + + return false +} diff --git a/internal/services/plugin.go b/internal/services/plugin.go index 29a91169..bba316ac 100644 --- a/internal/services/plugin.go +++ b/internal/services/plugin.go @@ -3,27 +3,9 @@ package services import ( "github.com/goravel/framework/facades" - "panel/internal" "panel/app/models" - "panel/internal/plugins/fail2ban" - "panel/internal/plugins/mysql57" - "panel/internal/plugins/mysql80" - "panel/internal/plugins/openresty" - "panel/internal/plugins/php74" - "panel/internal/plugins/php80" - "panel/internal/plugins/php81" - "panel/internal/plugins/php82" - "panel/internal/plugins/php83" - "panel/internal/plugins/phpmyadmin" - "panel/internal/plugins/postgresql15" - "panel/internal/plugins/postgresql16" - "panel/internal/plugins/pureftpd" - "panel/internal/plugins/redis" - "panel/internal/plugins/rsync" - "panel/internal/plugins/s3fs" - "panel/internal/plugins/supervisor" - "panel/internal/plugins/toolbox" + "panel/internal" ) type PluginImpl struct { @@ -45,208 +27,28 @@ func (r *PluginImpl) AllInstalled() ([]models.Plugin, error) { // All 获取所有插件 func (r *PluginImpl) All() []internal.PanelPlugin { - var p []internal.PanelPlugin + var plugins = []internal.PanelPlugin{ + internal.PluginOpenResty, + internal.PluginMySQL57, + internal.PluginMySQL80, + internal.PluginPostgreSQL15, + internal.PluginPostgreSQL16, + internal.PluginPHP74, + internal.PluginPHP80, + internal.PluginPHP81, + internal.PluginPHP82, + internal.PluginPHP83, + internal.PluginPHPMyAdmin, + internal.PluginPureFTPd, + internal.PluginRedis, + internal.PluginS3fs, + internal.PluginRsync, + internal.PluginSupervisor, + internal.PluginFail2ban, + internal.PluginToolBox, + } - p = append(p, internal.PanelPlugin{ - Name: openresty.Name, - Description: openresty.Description, - Slug: openresty.Slug, - Version: openresty.Version, - Requires: openresty.Requires, - Excludes: openresty.Excludes, - Install: openresty.Install, - Uninstall: openresty.Uninstall, - Update: openresty.Update, - }) - p = append(p, internal.PanelPlugin{ - Name: mysql57.Name, - Description: mysql57.Description, - Slug: mysql57.Slug, - Version: mysql57.Version, - Requires: mysql57.Requires, - Excludes: mysql57.Excludes, - Install: mysql57.Install, - Uninstall: mysql57.Uninstall, - Update: mysql57.Update, - }) - p = append(p, internal.PanelPlugin{ - Name: mysql80.Name, - Description: mysql80.Description, - Slug: mysql80.Slug, - Version: mysql80.Version, - Requires: mysql80.Requires, - Excludes: mysql80.Excludes, - Install: mysql80.Install, - Uninstall: mysql80.Uninstall, - Update: mysql80.Update, - }) - p = append(p, internal.PanelPlugin{ - Name: postgresql15.Name, - Description: postgresql15.Description, - Slug: postgresql15.Slug, - Version: postgresql15.Version, - Requires: postgresql15.Requires, - Excludes: postgresql15.Excludes, - Install: postgresql15.Install, - Uninstall: postgresql15.Uninstall, - Update: postgresql15.Update, - }) - p = append(p, internal.PanelPlugin{ - Name: postgresql16.Name, - Description: postgresql16.Description, - Slug: postgresql16.Slug, - Version: postgresql16.Version, - Requires: postgresql16.Requires, - Excludes: postgresql16.Excludes, - Install: postgresql16.Install, - Uninstall: postgresql16.Uninstall, - Update: postgresql16.Update, - }) - p = append(p, internal.PanelPlugin{ - Name: php74.Name, - Description: php74.Description, - Slug: php74.Slug, - Version: php74.Version, - Requires: php74.Requires, - Excludes: php74.Excludes, - Install: php74.Install, - Uninstall: php74.Uninstall, - Update: php74.Update, - }) - p = append(p, internal.PanelPlugin{ - Name: php80.Name, - Description: php80.Description, - Slug: php80.Slug, - Version: php80.Version, - Requires: php80.Requires, - Excludes: php80.Excludes, - Install: php80.Install, - Uninstall: php80.Uninstall, - Update: php80.Update, - }) - p = append(p, internal.PanelPlugin{ - Name: php81.Name, - Description: php81.Description, - Slug: php81.Slug, - Version: php81.Version, - Requires: php81.Requires, - Excludes: php81.Excludes, - Install: php81.Install, - Uninstall: php81.Uninstall, - Update: php81.Update, - }) - p = append(p, internal.PanelPlugin{ - Name: php82.Name, - Description: php82.Description, - Slug: php82.Slug, - Version: php82.Version, - Requires: php82.Requires, - Excludes: php82.Excludes, - Install: php82.Install, - Uninstall: php82.Uninstall, - Update: php82.Update, - }) - p = append(p, internal.PanelPlugin{ - Name: php83.Name, - Description: php83.Description, - Slug: php83.Slug, - Version: php83.Version, - Requires: php83.Requires, - Excludes: php83.Excludes, - Install: php83.Install, - Uninstall: php83.Uninstall, - Update: php83.Update, - }) - p = append(p, internal.PanelPlugin{ - Name: phpmyadmin.Name, - Description: phpmyadmin.Description, - Slug: phpmyadmin.Slug, - Version: phpmyadmin.Version, - Requires: phpmyadmin.Requires, - Excludes: phpmyadmin.Excludes, - Install: phpmyadmin.Install, - Uninstall: phpmyadmin.Uninstall, - Update: phpmyadmin.Update, - }) - p = append(p, internal.PanelPlugin{ - Name: pureftpd.Name, - Description: pureftpd.Description, - Slug: pureftpd.Slug, - Version: pureftpd.Version, - Requires: pureftpd.Requires, - Excludes: pureftpd.Excludes, - Install: pureftpd.Install, - Uninstall: pureftpd.Uninstall, - Update: pureftpd.Update, - }) - p = append(p, internal.PanelPlugin{ - Name: redis.Name, - Description: redis.Description, - Slug: redis.Slug, - Version: redis.Version, - Requires: redis.Requires, - Excludes: redis.Excludes, - Install: redis.Install, - Uninstall: redis.Uninstall, - Update: redis.Update, - }) - p = append(p, internal.PanelPlugin{ - Name: s3fs.Name, - Description: s3fs.Description, - Slug: s3fs.Slug, - Version: s3fs.Version, - Requires: s3fs.Requires, - Excludes: s3fs.Excludes, - Install: s3fs.Install, - Uninstall: s3fs.Uninstall, - Update: s3fs.Update, - }) - p = append(p, internal.PanelPlugin{ - Name: supervisor.Name, - Description: supervisor.Description, - Slug: supervisor.Slug, - Version: supervisor.Version, - Requires: supervisor.Requires, - Excludes: supervisor.Excludes, - Install: supervisor.Install, - Uninstall: supervisor.Uninstall, - Update: supervisor.Update, - }) - p = append(p, internal.PanelPlugin{ - Name: fail2ban.Name, - Description: fail2ban.Description, - Slug: fail2ban.Slug, - Version: fail2ban.Version, - Requires: fail2ban.Requires, - Excludes: fail2ban.Excludes, - Install: fail2ban.Install, - Uninstall: fail2ban.Uninstall, - Update: fail2ban.Update, - }) - p = append(p, internal.PanelPlugin{ - Name: rsync.Name, - Description: rsync.Description, - Slug: rsync.Slug, - Version: rsync.Version, - Requires: rsync.Requires, - Excludes: rsync.Excludes, - Install: rsync.Install, - Uninstall: rsync.Uninstall, - Update: rsync.Update, - }) - p = append(p, internal.PanelPlugin{ - Name: toolbox.Name, - Description: toolbox.Description, - Slug: toolbox.Slug, - Version: toolbox.Version, - Requires: toolbox.Requires, - Excludes: toolbox.Excludes, - Install: toolbox.Install, - Uninstall: toolbox.Uninstall, - Update: toolbox.Update, - }) - - return p + return plugins } // GetBySlug 根据slug获取插件 diff --git a/routes/plugin.go b/routes/plugin.go index 4a14decc..20a1bd81 100644 --- a/routes/plugin.go +++ b/routes/plugin.go @@ -139,7 +139,7 @@ func Plugin() { route.Post("users/password", postgresql16Controller.SetUserPassword) }) r.Prefix("php74").Group(func(route route.Router) { - php74Controller := plugins.NewPhp74Controller() + php74Controller := plugins.NewPHPController(74) route.Get("status", php74Controller.Status) route.Post("reload", php74Controller.Reload) route.Post("start", php74Controller.Start) @@ -157,7 +157,7 @@ func Plugin() { route.Delete("extensions", php74Controller.UninstallExtension) }) r.Prefix("php80").Group(func(route route.Router) { - php80Controller := plugins.NewPhp80Controller() + php80Controller := plugins.NewPHPController(80) route.Get("status", php80Controller.Status) route.Post("reload", php80Controller.Reload) route.Post("start", php80Controller.Start) @@ -175,7 +175,7 @@ func Plugin() { route.Delete("extensions", php80Controller.UninstallExtension) }) r.Prefix("php81").Group(func(route route.Router) { - php81Controller := plugins.NewPhp81Controller() + php81Controller := plugins.NewPHPController(81) route.Get("status", php81Controller.Status) route.Post("reload", php81Controller.Reload) route.Post("start", php81Controller.Start) @@ -193,7 +193,7 @@ func Plugin() { route.Delete("extensions", php81Controller.UninstallExtension) }) r.Prefix("php82").Group(func(route route.Router) { - php82Controller := plugins.NewPhp82Controller() + php82Controller := plugins.NewPHPController(82) route.Get("status", php82Controller.Status) route.Post("reload", php82Controller.Reload) route.Post("start", php82Controller.Start) @@ -211,7 +211,7 @@ func Plugin() { route.Delete("extensions", php82Controller.UninstallExtension) }) r.Prefix("php83").Group(func(route route.Router) { - php83Controller := plugins.NewPhp83Controller() + php83Controller := plugins.NewPHPController(83) route.Get("status", php83Controller.Status) route.Post("reload", php83Controller.Reload) route.Post("start", php83Controller.Start) diff --git a/scripts/php/install.sh b/scripts/php/install.sh index b0c3b62c..73614505 100644 --- a/scripts/php/install.sh +++ b/scripts/php/install.sh @@ -122,9 +122,9 @@ fi # 配置 cd src if [ "${phpVersion}" == "81" ] || [ "${phpVersion}" == "82" ] || [ "${phpVersion}" == "83" ]; then - ./configure --prefix=${phpPath} --with-config-file-path=${phpPath}/etc --enable-fpm --with-fpm-user=www --with-fpm-group=www --enable-mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-freetype --with-jpeg --with-zlib --enable-xml --disable-rpath --enable-bcmath --enable-shmop --enable-sysvsem --with-curl --enable-mbregex --enable-mbstring --enable-intl --enable-pcntl --enable-ftp --enable-gd --with-openssl --with-mhash --enable-pcntl --enable-sockets --enable-soap --with-gettext --enable-fileinfo --enable-opcache --with-sodium --with-webp --with-avif + ./configure --prefix=${phpPath} --with-config-file-path=${phpPath}/etc --enable-fpm --with-fpm-user=www --with-fpm-group=www --enable-mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-freetype --with-jpeg --with-zlib --enable-xml --disable-rpath --enable-bcmath --enable-shmop --with-curl --enable-mbregex --enable-mbstring --enable-pcntl --enable-ftp --enable-gd --with-openssl --with-mhash --enable-pcntl --enable-sockets --enable-soap --with-gettext --enable-fileinfo --enable-opcache --with-sodium --with-webp --with-avif else - ./configure --prefix=${phpPath} --with-config-file-path=${phpPath}/etc --enable-fpm --with-fpm-user=www --with-fpm-group=www --enable-mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-freetype --with-jpeg --with-zlib --with-libxml-dir=/usr --enable-xml --disable-rpath --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --enable-mbregex --enable-mbstring --enable-intl --enable-pcntl --enable-ftp --enable-gd --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-xmlrpc --enable-soap --with-gettext --enable-fileinfo --enable-opcache --with-sodium --with-webp + ./configure --prefix=${phpPath} --with-config-file-path=${phpPath}/etc --enable-fpm --with-fpm-user=www --with-fpm-group=www --enable-mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-freetype --with-jpeg --with-zlib --with-libxml-dir=/usr --enable-xml --disable-rpath --enable-bcmath --enable-shmop --enable-inline-optimization --with-curl --enable-mbregex --enable-mbstring --enable-pcntl --enable-ftp --enable-gd --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-xmlrpc --enable-soap --with-gettext --enable-fileinfo --enable-opcache --with-sodium --with-webp fi # 编译安装 diff --git a/scripts/php_extensions/exif.sh b/scripts/php_extensions/exif.sh deleted file mode 100644 index eb894906..00000000 --- a/scripts/php_extensions/exif.sh +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/bash -export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH - -: ' -Copyright (C) 2022 - now HaoZi Technology Co., Ltd. - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published -by the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -' - -HR="+----------------------------------------------------" - -action="$1" # 操作 -phpVersion="$2" # PHP版本 - -Install() { - # 检查是否已经安装 - isInstall=$(cat /www/server/php/${phpVersion}/etc/php.ini | grep '^extension=exif$') - if [ "${isInstall}" != "" ]; then - echo -e $HR - echo "PHP-${phpVersion} 已安装 exif" - exit 1 - fi - - cd /www/server/php/${phpVersion}/src/ext/exif - /www/server/php/${phpVersion}/bin/phpize - ./configure --with-php-config=/www/server/php/${phpVersion}/bin/php-config - make - if [ "$?" != "0" ]; then - echo -e $HR - echo "PHP-${phpVersion} exif 编译失败" - exit 1 - fi - make install - if [ "$?" != "0" ]; then - echo -e $HR - echo "PHP-${phpVersion} exif 安装失败" - exit 1 - fi - - sed -i '/;haozi/a\extension=exif' /www/server/php/${phpVersion}/etc/php.ini - - # 重载PHP - systemctl reload php-fpm-${phpVersion}.service - echo -e $HR - echo "PHP-${phpVersion} exif 安装成功" -} - -Uninstall() { - # 检查是否已经安装 - isInstall=$(cat /www/server/php/${phpVersion}/etc/php.ini | grep '^extension=exif$') - if [ "${isInstall}" == "" ]; then - echo -e $HR - echo "PHP-${phpVersion} 未安装 exif" - exit 1 - fi - - sed -i '/extension=exif/d' /www/server/php/${phpVersion}/etc/php.ini - - # 重载PHP - systemctl reload php-fpm-${phpVersion}.service - echo -e $HR - echo "PHP-${phpVersion} exif 卸载成功" -} - -if [ "$action" == 'install' ]; then - Install -fi -if [ "$action" == 'uninstall' ]; then - Uninstall -fi diff --git a/scripts/php_extensions/official.sh b/scripts/php_extensions/official.sh new file mode 100644 index 00000000..3d624e6a --- /dev/null +++ b/scripts/php_extensions/official.sh @@ -0,0 +1,162 @@ +#!/bin/bash +export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH + +: ' +Copyright (C) 2022 - now HaoZi Technology Co., Ltd. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +' + +HR="+----------------------------------------------------" +OS=$(source /etc/os-release && { [[ "$ID" == "debian" ]] && echo "debian"; } || { [[ "$ID" == "centos" ]] || [[ "$ID" == "rhel" ]] || [[ "$ID" == "rocky" ]] || [[ "$ID" == "almalinux" ]] && echo "centos"; } || echo "unknown") + +action="$1" # 操作 +phpVersion="$2" # PHP版本 +extensionName="$3" # 扩展名称 +addArgs="" # 附加参数 + +Install() { + # 检查是否已经安装 + isInstall=$(cat /www/server/php/${phpVersion}/etc/php.ini | grep "^extension=${extensionName}$") + if [ "${isInstall}" != "" ]; then + echo -e $HR + echo "PHP-${phpVersion} 已安装 ${extensionName}" + exit 1 + fi + + # 安装依赖 + if [ "${extensionName}" == "snmp" ]; then + if [ "${OS}" == "centos" ]; then + dnf install -y net-snmp-devel + elif [ "${OS}" == "debian" ]; then + apt-get install -y libsnmp-dev + fi + fi + if [ "${extensionName}" == "ldap" ]; then + if [ "${OS}" == "centos" ]; then + dnf install -y openldap-devel + ln -sf /usr/lib64/libldap* /usr/lib + elif [ "${OS}" == "debian" ]; then + apt-get install -y libldap2-dev + ln -sf /usr/lib/x86_64-linux-gnu/libldap* /usr/lib + fi + fi + if [ "${extensionName}" == "imap" ]; then + if [ "${OS}" == "centos" ]; then + # RHEL 9 的仓库中没有 libc-client-devel,待考虑 + dnf install -y libc-client-devel + elif [ "${OS}" == "debian" ]; then + apt-get install -y libc-client-dev + fi + addArgs="--with-imap --with-imap-ssl --with-kerberos" + fi + if [ "${extensionName}" == "enchant" ]; then + if [ "${OS}" == "centos" ]; then + dnf install -y enchant-devel + elif [ "${OS}" == "debian" ]; then + apt-get install -y libenchant-2-dev + fi + fi + if [ "${extensionName}" == "pspell" ]; then + if [ "${OS}" == "centos" ]; then + dnf install -y aspell-devel + elif [ "${OS}" == "debian" ]; then + apt-get install -y libpspell-dev + fi + fi + if [ "${extensionName}" == "gmp" ]; then + if [ "${OS}" == "centos" ]; then + dnf install -y gmp-devel + elif [ "${OS}" == "debian" ]; then + apt-get install -y libgmp-dev + fi + fi + if [ "${extensionName}" == "gettext" ]; then + if [ "${OS}" == "centos" ]; then + dnf install -y gettext-devel + elif [ "${OS}" == "debian" ]; then + apt-get install -y libgettextpo-dev + fi + fi + if [ "${extensionName}" == "bz2" ]; then + if [ "${OS}" == "centos" ]; then + dnf install -y bzip2-devel + elif [ "${OS}" == "debian" ]; then + apt-get install -y libbz2-dev + fi + fi + if [ "${extensionName}" == "zip" ]; then + if [ "${OS}" == "centos" ]; then + dnf install -y libzip-devel + elif [ "${OS}" == "debian" ]; then + apt-get install -y libzip-dev + fi + fi + if [ "${extensionName}" == "pdo_pgsql" ]; then + addArgs="--with-pdo-pgsql=/www/server/postgresql" + fi + + # 安装扩展 + if [ ! -d /www/server/php/${phpVersion}/src/ext/${extensionName} ]; then + echo -e $HR + echo "PHP-${phpVersion} ${extensionName} 源码不存在" + exit 1 + fi + cd /www/server/php/${phpVersion}/src/ext/${extensionName} + /www/server/php/${phpVersion}/bin/phpize + ./configure --with-php-config=/www/server/php/${phpVersion}/bin/php-config ${addArgs} + make + if [ "$?" != "0" ]; then + echo -e $HR + echo "PHP-${phpVersion} ${extensionName} 编译失败" + exit 1 + fi + make install + if [ "$?" != "0" ]; then + echo -e $HR + echo "PHP-${phpVersion} ${extensionName} 安装失败" + exit 1 + fi + + sed -i "/;haozi/a\extension=${extensionName}" /www/server/php/${phpVersion}/etc/php.ini + + # 重载PHP + systemctl reload php-fpm-${phpVersion}.service + echo -e $HR + echo "PHP-${phpVersion} ${extensionName} 安装成功" +} + +Uninstall() { + # 检查是否已经安装 + isInstall=$(cat /www/server/php/${phpVersion}/etc/php.ini | grep "^extension=${extensionName}$") + if [ "${isInstall}" == "" ]; then + echo -e $HR + echo "PHP-${phpVersion} 未安装 ${extensionName}" + exit 1 + fi + + sed -i "/extension=${extensionName}/d" /www/server/php/${phpVersion}/etc/php.ini + + # 重载PHP + systemctl reload php-fpm-${phpVersion}.service + echo -e $HR + echo "PHP-${phpVersion} ${extensionName} 卸载成功" +} + +if [ "$action" == 'install' ]; then + Install +fi +if [ "$action" == 'uninstall' ]; then + Uninstall +fi diff --git a/scripts/php_extensions/pdo_pgsql.sh b/scripts/php_extensions/pdo_pgsql.sh deleted file mode 100644 index 134a527a..00000000 --- a/scripts/php_extensions/pdo_pgsql.sh +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/bash -export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH - -: ' -Copyright (C) 2022 - now HaoZi Technology Co., Ltd. - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published -by the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -' - -HR="+----------------------------------------------------" - -action="$1" -phpVersion="$2" - -Install() { - # 检查是否已经安装 - isInstall=$(cat /www/server/php/${phpVersion}/etc/php.ini | grep '^extension=pdo_pgsql$') - if [ "${isInstall}" != "" ]; then - echo -e $HR - echo "PHP-${phpVersion} 已安装 pdo_pgsql" - exit 1 - fi - - cd /www/server/php/${phpVersion}/src/ext/pdo_pgsql - /www/server/php/${phpVersion}/bin/phpize - ./configure --with-php-config=/www/server/php/${phpVersion}/bin/php-config --with-pdo-pgsql=/www/server/postgresql - make - if [ "$?" != "0" ]; then - echo -e $HR - echo "PHP-${phpVersion} pdo_pgsql 编译失败" - exit 1 - fi - make install - if [ "$?" != "0" ]; then - echo -e $HR - echo "PHP-${phpVersion} pdo_pgsql 安装失败" - exit 1 - fi - - sed -i '/;haozi/a\extension=pdo_pgsql' /www/server/php/${phpVersion}/etc/php.ini - - # 重载PHP - systemctl reload php-fpm-${phpVersion}.service - echo -e $HR - echo "PHP-${phpVersion} pdo_pgsql 安装成功" -} - -Uninstall() { - # 检查是否已经安装 - isInstall=$(cat /www/server/php/${phpVersion}/etc/php.ini | grep '^extension=pdo_pgsql$') - if [ "${isInstall}" == "" ]; then - echo -e $HR - echo "PHP-${phpVersion} 未安装 pdo_pgsql" - exit 1 - fi - - sed -i '/extension=pdo_pgsql/d' /www/server/php/${phpVersion}/etc/php.ini - - # 重载PHP - systemctl reload php-fpm-${phpVersion}.service - echo -e $HR - echo "PHP-${phpVersion} pdo_pgsql 卸载成功" -} - -if [ "$action" == 'install' ]; then - Install -fi -if [ "$action" == 'uninstall' ]; then - Uninstall -fi