diff --git a/UI b/UI index 65d4738..f3088b6 160000 --- a/UI +++ b/UI @@ -1 +1 @@ -Subproject commit 65d4738a607ec28f22bffb1d489dd284c360d2ce +Subproject commit f3088b635482fd4330c3fce6bbfcd1f70ff8024a diff --git a/model/app.go b/model/app.go index d1ab241..a1ab39b 100644 --- a/model/app.go +++ b/model/app.go @@ -15,6 +15,7 @@ type ServerAppList struct { Icon string `json:"icon"` ScreenshotLink Strings `gorm:"type:json" json:"screenshot_link"` Category string `json:"category"` + CategoryFont string `json:"category_font"` PortMap string `json:"port_map"` ImageVersion string `json:"image_version"` Tip string `json:"tip"` @@ -36,6 +37,8 @@ type ServerAppList struct { Healthy string `json:"healthy"` Plugins Strings `json:"plugins"` Origin string `json:"origin"` + Type int `json:"type"` + Developer string `json:"developer"` } type Ports struct { diff --git a/model/category.go b/model/category.go index 2040730..04a05ab 100644 --- a/model/category.go +++ b/model/category.go @@ -5,6 +5,7 @@ type ServerCategoryList struct { //CreatedAt time.Time `json:"created_at"` // //UpdatedAt time.Time `json:"updated_at"` + Font string `json:"font"` Name string `json:"name"` Count uint `json:"count"` } diff --git a/pkg/docker/volumes.go b/pkg/docker/volumes.go index 22389a5..d782a20 100644 --- a/pkg/docker/volumes.go +++ b/pkg/docker/volumes.go @@ -3,33 +3,9 @@ package docker import "strings" func GetDir(id, envName string) string { - var path string - if len(id) == 0 { - id = "$AppID" + if strings.Contains(envName, "$AppID") && len(id) > 0 { + return strings.ReplaceAll(envName, "$AppID", id) } - - switch { - case strings.Contains(strings.ToLower(envName), "config") || strings.Contains(strings.ToLower(envName), "photoprism/storage") || strings.Contains(strings.ToLower(envName), "config"): - path = "/DATA/AppData/" + id + "/" - case strings.Contains(strings.ToLower(envName), "media"): - path = "/DATA/Media/" - case strings.Contains(strings.ToLower(envName), "movie"): - path = "/DATA/Media/Movies/" - case strings.Contains(strings.ToLower(envName), "music"): - path = "/DATA/Media/Music/" - case strings.Contains(strings.ToLower(envName), "photoprism/originals"): - path = "/DATA/Gallery" - case strings.Contains(strings.ToLower(envName), "download"): - path = "/DATA/Downloads/" - case strings.Contains(strings.ToLower(envName), "photo") || strings.Contains(strings.ToLower(envName), "pictures"): - path = "/DATA/Downloads/" - case strings.ToLower(envName) == "/srv": - path = "/DATA/" - case strings.ToLower(envName) == "/tv": - path = "/DATA/Media/TV Shows" - default: - //path = "/media" - } - return path + return envName } diff --git a/pkg/sqlite/db.go b/pkg/sqlite/db.go index debf02a..dcbaf10 100644 --- a/pkg/sqlite/db.go +++ b/pkg/sqlite/db.go @@ -2,11 +2,12 @@ package sqlite import ( "fmt" + "time" + "github.com/IceWhaleTech/CasaOS/pkg/utils/file" model2 "github.com/IceWhaleTech/CasaOS/service/model" "gorm.io/driver/sqlite" "gorm.io/gorm" - "time" ) var gdb *gorm.DB @@ -30,7 +31,7 @@ func GetDb(projectPath string) *gorm.DB { return nil } gdb = db - err = db.AutoMigrate(&model2.TaskDBModel{}, &model2.AppNotify{}, &model2.AppListDBModel{}) + err = db.AutoMigrate(&model2.TaskDBModel{}, &model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}) if err != nil { fmt.Println("检查和创建数据库出错", err) } diff --git a/pkg/utils/command/command_helper.go b/pkg/utils/command/command_helper.go index 26dd4c3..aa9ce1a 100644 --- a/pkg/utils/command/command_helper.go +++ b/pkg/utils/command/command_helper.go @@ -75,6 +75,7 @@ func ExecResultStr(cmdStr string) string { func ExecLSBLK() []byte { output, err := exec.Command("lsblk", "-O", "-J", "-b").Output() if err != nil { + fmt.Println("lsblk", err) return nil } return output diff --git a/pkg/utils/env_helper/env.go b/pkg/utils/env_helper/env.go index e98a103..b6894e1 100644 --- a/pkg/utils/env_helper/env.go +++ b/pkg/utils/env_helper/env.go @@ -2,18 +2,25 @@ package env_helper import "strings" -func ReplaceDefaultENV(key string) string { +func ReplaceDefaultENV(key, tz string) string { temp := "" switch key { case "$DefaultPassword": temp = "casaos" case "$DefaultUserName": temp = "admin" + + case "$PUID": + temp = "1000" + case "$PGID": + temp = "1000" + case "$TZ": + temp = tz } return temp } //replace env default setting func ReplaceStringDefaultENV(str string) string { - return strings.ReplaceAll(strings.ReplaceAll(str, "$DefaultPassword", ReplaceDefaultENV("$DefaultPassword")), "$DefaultUserName", ReplaceDefaultENV("$DefaultUserName")) + return strings.ReplaceAll(strings.ReplaceAll(str, "$DefaultPassword", ReplaceDefaultENV("$DefaultPassword", "")), "$DefaultUserName", ReplaceDefaultENV("$DefaultUserName", "")) } diff --git a/route/init.go b/route/init.go index c982eb6..c2af48d 100644 --- a/route/init.go +++ b/route/init.go @@ -22,6 +22,8 @@ import ( func InitFunction() { go checkSystemApp() Update2_3() + CheckSerialDiskMount() + } var syncIsExistence = false @@ -72,9 +74,6 @@ func installSyncthing(appId string) { appInfo.Tip = env_helper.ReplaceStringDefaultENV(appInfo.Tip) } - for i := 0; i < len(appInfo.Volumes); i++ { - appInfo.Volumes[i].Path = docker.GetDir("", appInfo.Volumes[i].ContainerPath) - } appInfo.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20 id := uuid.NewV4().String() @@ -171,7 +170,7 @@ func checkSystemApp() { path := "" for _, i := range paths { if i.ContainerPath == "/config" { - path = docker.GetDir(v.CustomId, i.ContainerPath) + "config.xml" + path = docker.GetDir(v.CustomId, i.Path) + "config.xml" for i := 0; i < 10; i++ { if file.CheckNotExist(path) { time.Sleep(1 * time.Second) @@ -189,12 +188,31 @@ func checkSystemApp() { } } if !syncIsExistence { - installSyncthing("44") + installSyncthing("74") } } func CheckSerialDiskMount() { - // 检查挂载点重新挂载 - // 检查新硬盘是否有多个分区,如有多个分区需提示 + // check mount point + dbList := service.MyService.Disk().GetSerialAll() + + list := service.MyService.Disk().LSBLK() + mountPoint := make(map[string]string, len(dbList)) + + for _, v := range list { + if v.Children != nil { + for _, h := range v.Children { + mountPoint[h.MountPoint] = "1" + } + } + } + + //remount + for _, item := range dbList { + if _, ok := mountPoint[item.MountPoint]; !ok { + service.MyService.Disk().MountDisk(item.Path, item.MountPoint) + } + } + } func Update2_3() { command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/assist.sh") diff --git a/route/route.go b/route/route.go index dea3fea..db0c19e 100644 --- a/route/route.go +++ b/route/route.go @@ -70,8 +70,7 @@ func InitRouter() *gin.Engine { //获取网络信息 v1ZiMaGroup.GET("/getnetinfo", v1.NetInfo) - //获取网络信息 - v1ZiMaGroup.GET("/getinfo", v1.Info) + //获取系统信息 v1ZiMaGroup.GET("/sysinfo", v1.SysInfo) } @@ -197,6 +196,7 @@ func InitRouter() *gin.Engine { v1SysGroup.GET("/port", v1.GetCasaOSPort) v1SysGroup.PUT("/port", v1.PutCasaOSPort) v1SysGroup.POST("/kill", v1.PostKillCasaOS) + v1SysGroup.GET("/info", v1.Info) } v1FileGroup := v1Group.Group("/file") v1FileGroup.Use() @@ -211,11 +211,13 @@ func InitRouter() *gin.Engine { v1FileGroup.POST("/create", v1.PostCreateFile) v1FileGroup.GET("/download", v1.GetDownloadFile) + v1FileGroup.PUT("/move", v1.PutFileMove) //v1FileGroup.GET("/download", v1.UserFileDownloadCommonService) } v1DiskGroup := v1Group.Group("/disk") v1DiskGroup.Use() { + v1DiskGroup.GET("/check", v1.GetDiskCheck) //获取磁盘列表 v1DiskGroup.GET("/list", v1.GetPlugInDisk) @@ -238,8 +240,8 @@ func InitRouter() *gin.Engine { v1DiskGroup.POST("/mount", v1.PostMountDisk) //umount SATA disk - v1DiskGroup.POST("/umount", v1.DeleteUmountDisk) - + v1DiskGroup.POST("/umount", v1.PostDiskUmount) + v1DiskGroup.DELETE("/remove/:id", v1.DeleteDisk) } v1ShareGroup := v1Group.Group("/share") v1ShareGroup.Use() diff --git a/route/v1/app.go b/route/v1/app.go index be96822..9fe0597 100644 --- a/route/v1/app.go +++ b/route/v1/app.go @@ -7,8 +7,6 @@ import ( "strconv" "github.com/IceWhaleTech/CasaOS/model" - "github.com/IceWhaleTech/CasaOS/pkg/docker" - "github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper" "github.com/IceWhaleTech/CasaOS/pkg/utils/file" oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err" port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port" @@ -33,20 +31,33 @@ func AppList(c *gin.Context) { //service.MyService.Docker().DockerContainerCommit("test2") index := c.DefaultQuery("index", "1") - size := c.DefaultQuery("size", "10") + size := c.DefaultQuery("size", "10000") t := c.DefaultQuery("type", "rank") categoryId := c.DefaultQuery("category_id", "0") key := c.DefaultQuery("key", "") - list, count := service.MyService.OAPI().GetServerList(index, size, t, categoryId, key) + recommend, list, community := service.MyService.OAPI().GetServerList(index, size, t, categoryId, key) + for i := 0; i < len(recommend); i++ { + ct, _ := service.MyService.Docker().DockerListByImage(recommend[i].Image, recommend[i].ImageVersion) + if ct != nil { + list[i].State = ct.State + } + } for i := 0; i < len(list); i++ { ct, _ := service.MyService.Docker().DockerListByImage(list[i].Image, list[i].ImageVersion) if ct != nil { list[i].State = ct.State } } - data := make(map[string]interface{}, 2) - data["count"] = count - data["items"] = list + for i := 0; i < len(community); i++ { + ct, _ := service.MyService.Docker().DockerListByImage(community[i].Image, community[i].ImageVersion) + if ct != nil { + list[i].State = ct.State + } + } + data := make(map[string]interface{}, 3) + data["recommend"] = recommend + data["list"] = list + data["community"] = community c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data}) } @@ -147,6 +158,13 @@ func AppInfo(c *gin.Context) { info.PortMap = info.Ports[i].CommendPort } } + } else { + for i := 0; i < len(info.Ports); i++ { + if info.Ports[i].Type == 0 { + info.PortMap = info.Ports[i].ContainerPort + break + } + } } for i := 0; i < len(info.Devices); i++ { @@ -154,13 +172,10 @@ func AppInfo(c *gin.Context) { info.Devices[i].Path = info.Devices[i].ContainerPath } } - if len(info.Tip) > 0 { - info.Tip = env_helper.ReplaceStringDefaultENV(info.Tip) - } + // if len(info.Tip) > 0 { + // info.Tip = env_helper.ReplaceStringDefaultENV(info.Tip) + // } - for i := 0; i < len(info.Volumes); i++ { - info.Volumes[i].Path = docker.GetDir("", info.Volumes[i].ContainerPath) - } // portOrder := func(c1, c2 *model.Ports) bool { // return c1.Type < c2.Type // } @@ -207,7 +222,7 @@ func CategoryList(c *gin.Context) { } rear := append([]model.ServerCategoryList{}, list[0:]...) - list = append(list[:0], model.ServerCategoryList{Count: count, Name: "All"}) + list = append(list[:0], model.ServerCategoryList{Count: count, Name: "All", Font: "apps"}) list = append(list, rear...) c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list}) } diff --git a/route/v1/disk.go b/route/v1/disk.go index 378f2bd..17df806 100644 --- a/route/v1/disk.go +++ b/route/v1/disk.go @@ -2,10 +2,12 @@ package v1 import ( "net/http" + "strconv" "github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err" "github.com/IceWhaleTech/CasaOS/service" + model2 "github.com/IceWhaleTech/CasaOS/service/model" "github.com/gin-gonic/gin" "github.com/shirou/gopsutil/v3/disk" ) @@ -19,44 +21,9 @@ import ( // @Router /disk/list [get] func GetPlugInDisk(c *gin.Context) { - //ls := service.MyService.Disk().GetPlugInDisk() - //fmt.Println(ls) - //dd, _ := disk.Partitions(true) - //fmt.Println(dd) - // - //dir, err := ioutil.ReadDir("/sys/block") - //if err != nil { - // panic(err) - //} - // - //files := make([]string, 0) - // - ////fmt.Println(regexp.MatchString("sd[a-z]*[0-9]", "sda")) - // - //for _, f := range dir { - // if match, _ := regexp.MatchString("sd[a-z]", f.Name()); match { - // files = append(files, f.Name()) - // } - //} - //fmt.Println(files) - //filess := make([]string, 0) - //for _, file := range files { - // dirs, _ := ioutil.ReadDir("/sys/block/" + file) - // - // for _, f := range dirs { - // if match, _ := regexp.MatchString("sd[a-z]*[0-9]", f.Name()); match { - // filess = append(filess, f.Name()) - // } - // } - //} - //fmt.Println(filess) - // - //for _, s := range filess { - // fmt.Println(disk.Usage("/dev/" + s)) - //} + list := service.MyService.Disk().LSBLK() - lst := service.MyService.Disk().LSBLK() - c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: lst}) + c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: list}) } // @Summary get disk list @@ -98,7 +65,7 @@ func GetDiskInfo(c *gin.Context) { // @Accept multipart/form-data // @Tags disk // @Security ApiKeyAuth -// @Param path formData string true "磁盘路径 例如/dev/sda1" +// @Param path formData string true "for example /dev/sda1" // @Success 200 {string} string "ok" // @Router /disk/format [post] func FormatDisk(c *gin.Context) { @@ -108,8 +75,8 @@ func FormatDisk(c *gin.Context) { if len(path) == 0 || len(t) == 0 { c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)}) + return } - //格式化磁盘 service.MyService.Disk().FormatDisk(path, t) c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)}) @@ -168,23 +135,106 @@ func AddPartition(c *gin.Context) { c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)}) } +// @Summary add mount point +// @Produce application/json +// @Accept multipart/form-data +// @Tags disk +// @Security ApiKeyAuth +// @Param path formData string true "for example: /dev/sda1" +// @Param serial formData string true "disk id" +// @Success 200 {string} string "ok" +// @Router /disk/mount [post] func PostMountDisk(c *gin.Context) { // for example: path=/dev/sda1 path := c.PostForm("path") - //执行挂载目录 - service.MyService.Disk().MountDisk(path, "volume") - //添加到数据库 + serial := c.PostForm("serial") + mountPath := "/mnt/volume" + var list = service.MyService.Disk().GetSerialAll() + var pathMapList = make(map[string]string, len(list)) + for _, v := range list { + pathMapList[v.MountPoint] = "1" + } + + for i := 0; i < len(list)+1; i++ { + if _, ok := pathMapList[mountPath+strconv.Itoa(i)]; !ok { + mountPath = mountPath + strconv.Itoa(i) + break + } + } + + //mount dir + service.MyService.Disk().MountDisk(path, mountPath) + //save to data + m := model2.SerialDisk{} + m.MountPoint = mountPath + m.Path = path + m.Serial = serial + m.State = 0 + service.MyService.Disk().SaveMountPoint(m) c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)}) } -func DeleteUmountDisk(c *gin.Context) { +// @Summary remove mount point +// @Produce application/json +// @Accept multipart/form-data +// @Tags disk +// @Security ApiKeyAuth +// @Param path formData string true "for example: /dev/sda1" +// @Param mount_point formData string true "for example: /mnt/volume1" +// @Success 200 {string} string "ok" +// @Router /disk/umount [post] +func PostDiskUmount(c *gin.Context) { - // for example: path=/dev/sda1 + // path := c.PostForm("path") + mountPoint := c.PostForm("mount_point") service.MyService.Disk().UmountPointAndRemoveDir(path) - //删除数据库记录 + //delete data + service.MyService.Disk().DeleteMountPoint(path, mountPoint) + c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)}) +} + +// @Summary confirm delete disk +// @Produce application/json +// @Accept application/json +// @Tags disk +// @Security ApiKeyAuth +// @Param id path string true "id" +// @Success 200 {string} string "ok" +// @Router /disk/remove/{id} [delete] +func DeleteDisk(c *gin.Context) { + id := c.Param("id") + service.MyService.Disk().DeleteMount(id) + c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)}) +} + +// @Summary check mount point +// @Produce application/json +// @Accept application/json +// @Tags disk +// @Security ApiKeyAuth +// @Success 200 {string} string "ok" +// @Router /disk/init [get] +func GetDiskCheck(c *gin.Context) { + + dbList := service.MyService.Disk().GetSerialAll() + list := service.MyService.Disk().LSBLK() + + mapList := make(map[string]string) + + for _, v := range list { + mapList[v.Serial] = "1" + } + + for _, v := range dbList { + if _, ok := mapList[v.Serial]; !ok { + //disk undefind + c.JSON(http.StatusOK, model.Result{Success: oasis_err.ERROR, Message: oasis_err.GetMsg(oasis_err.ERROR), Data: "disk undefind"}) + return + } + } c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)}) } diff --git a/route/v1/docker.go b/route/v1/docker.go index 44bfbf3..241a6bd 100644 --- a/route/v1/docker.go +++ b/route/v1/docker.go @@ -218,14 +218,24 @@ func InstallApp(c *gin.Context) { } } + if m.Origin == "custom" { + for _, device := range m.Devices { + if file.CheckNotExist(device.Path) { + c.JSON(http.StatusOK, model.Result{Success: oasis_err2.DEVICE_NOT_EXIST, Message: device.Path + "," + oasis_err2.GetMsg(oasis_err2.DEVICE_NOT_EXIST)}) + return + } - for _, device := range m.Devices { - if file.CheckNotExist(device.Path) { - c.JSON(http.StatusOK, model.Result{Success: oasis_err2.DEVICE_NOT_EXIST, Message: device.Path + "," + oasis_err2.GetMsg(oasis_err2.DEVICE_NOT_EXIST)}) - return } - + } else { + dev := []model.PathMap{} + for _, device := range dev { + if !file.CheckNotExist(device.Path) { + dev = append(dev, device) + } + } + m.Devices = dev } + //restart := c.PostForm("restart") //always 总是重启, unless-stopped 除非用户手动停止容器,否则总是重新启动, on-failure:仅当容器退出代码非零时重新启动 //if len(restart) > 0 { // @@ -421,11 +431,11 @@ func InstallApp(c *gin.Context) { rely := model.MapStrings{} copier.Copy(&rely, &relyMap) - if m.Origin != "custom" { - for i := 0; i < len(m.Volumes); i++ { - m.Volumes[i].Path = docker.GetDir(id, m.Volumes[i].ContainerPath) - } - } + // if m.Origin != "custom" { + // for i := 0; i < len(m.Volumes); i++ { + // m.Volumes[i].Path = docker.GetDir(id, m.Volumes[i].Path) + // } + // } portsStr, _ := json2.Marshal(m.Ports) envsStr, _ := json2.Marshal(m.Envs) diff --git a/route/v1/file.go b/route/v1/file.go index 54eddef..e0c3204 100644 --- a/route/v1/file.go +++ b/route/v1/file.go @@ -9,6 +9,8 @@ import ( "net/http" "os" "path" + "path/filepath" + "time" "github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/pkg/utils/file" @@ -256,3 +258,64 @@ func PostFileUpload(c *gin.Context) { io.Copy(out, file) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)}) } + +func PutFileMove(c *gin.Context) { + from := "/Users/liangjianli/go/CasaOS" + to := "/Users/liangjianli/go/CasaOS/test" + //t := 1 //是否覆盖 + + //方法体 + stopCh := make(chan int) + f, err := os.Stat(from) + if err != nil { + //未拿到文件信息 + fmt.Println("stat", err) + } + //未创建新的文件夹 + if f.IsDir() { + //from 是文件夹,定义to也是文件夹 + if list, err := ioutil.ReadDir(from); err == nil { + for _, v := range list { + time.Sleep(time.Second) + if err = Copy(stopCh, filepath.Join(from, v.Name()), filepath.Join(to, v.Name())); err != nil { + fmt.Printf("copy %s ,err %d", v.Name(), err) + } + } + } + } else { + p := filepath.Dir(to) + if _, err = os.Stat(p); err != nil { + if err = os.MkdirAll(p, 0777); err != nil { + fmt.Println("mkdir", err) + } + } + } + + file, err := os.Open(from) + + if err != nil { + fmt.Println("open file error ", err) + } + defer file.Close() + out, err := os.Create(to) + if err != nil { + fmt.Println("create to file err", err) + } + defer out.Close() + io.Copy(out, file) + time.Sleep(time.Second * 4) + close(stopCh) +} +func Copy(stop chan int, from, to string) error { + + for { + select { + case <-stop: + return nil + default: + fmt.Println(from) + + } + } + return nil +} diff --git a/route/v1/system.go b/route/v1/system.go index 2bfcb7e..9f09c0d 100644 --- a/route/v1/system.go +++ b/route/v1/system.go @@ -6,11 +6,14 @@ import ( "net/http" "os" "strconv" + "strings" "time" + "unsafe" "github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err" + oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err" port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port" "github.com/IceWhaleTech/CasaOS/pkg/utils/version" "github.com/IceWhaleTech/CasaOS/service" @@ -127,8 +130,9 @@ func GetWidgetConfig(c *gin.Context) { func PostSetWidgetConfig(c *gin.Context) { buf := make([]byte, 1024) n, _ := c.Request.Body.Read(buf) - + fmt.Println("错误", strconv.Itoa(n)) service.MyService.System().UpSystemConfig("", string(buf[0:n])) + fmt.Println("错误1", string(buf[0:n])) c.JSON(http.StatusOK, model.Result{ Success: oasis_err.SUCCESS, @@ -221,3 +225,44 @@ func GetGuideCheck(c *gin.Context) { func PostKillCasaOS(c *gin.Context) { os.Exit(0) } + +// @Summary system info +// @Produce application/json +// @Accept application/json +// @Tags sys +// @Security ApiKeyAuth +// @Success 200 {string} string "ok" +// @Router /sys/info [get] +func Info(c *gin.Context) { + var data = make(map[string]interface{}, 5) + + list := service.MyService.Disk().LSBLK() + data["disk"] = list + cpu := service.MyService.ZiMa().GetCpuPercent() + num := service.MyService.ZiMa().GetCpuCoreNum() + cpuData := make(map[string]interface{}) + cpuData["percent"] = cpu + cpuData["num"] = num + data["cpu"] = cpuData + data["mem"] = service.MyService.ZiMa().GetMemInfo() + + //拼装网络信息 + netList := service.MyService.ZiMa().GetNetInfo() + newNet := []model.IOCountersStat{} + nets := service.MyService.ZiMa().GetNet(true) + for _, n := range netList { + for _, netCardName := range nets { + if n.Name == netCardName { + item := *(*model.IOCountersStat)(unsafe.Pointer(&n)) + item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name)) + item.DateTime = time.Now() + newNet = append(newNet, item) + break + } + } + } + + data["net"] = newNet + + c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data}) +} diff --git a/route/v1/zima_info.go b/route/v1/zima_info.go index c1ccb3a..fa7ba9e 100644 --- a/route/v1/zima_info.go +++ b/route/v1/zima_info.go @@ -1,15 +1,15 @@ package v1 import ( - "github.com/IceWhaleTech/CasaOS/model" - oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err" - "github.com/IceWhaleTech/CasaOS/service" - "github.com/gin-gonic/gin" - "github.com/shirou/gopsutil/v3/disk" "net/http" "strings" "time" "unsafe" + + "github.com/IceWhaleTech/CasaOS/model" + oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err" + "github.com/IceWhaleTech/CasaOS/service" + "github.com/gin-gonic/gin" ) // @Summary 获取cpu信息 @@ -83,48 +83,6 @@ func NetInfo(c *gin.Context) { c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: newNet}) } -// @Summary 获取信息 -// @Produce application/json -// @Accept application/json -// @Tags zima -// @Security ApiKeyAuth -// @Success 200 {string} string "ok" -// @Router /zima/getinfo [get] -func Info(c *gin.Context) { - var data = make(map[string]interface{}, 4) - - var diskArr []*disk.UsageStat - diskArr = append(diskArr, service.MyService.ZiMa().GetDiskInfo()) - data["disk"] = diskArr - cpu := service.MyService.ZiMa().GetCpuPercent() - num := service.MyService.ZiMa().GetCpuCoreNum() - cpuData := make(map[string]interface{}) - cpuData["percent"] = cpu - cpuData["num"] = num - data["cpu"] = cpuData - data["mem"] = service.MyService.ZiMa().GetMemInfo() - - //拼装网络信息 - netList := service.MyService.ZiMa().GetNetInfo() - newNet := []model.IOCountersStat{} - nets := service.MyService.ZiMa().GetNet(true) - for _, n := range netList { - for _, netCardName := range nets { - if n.Name == netCardName { - item := *(*model.IOCountersStat)(unsafe.Pointer(&n)) - item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name)) - item.DateTime = time.Now() - newNet = append(newNet, item) - break - } - } - } - - data["net"] = newNet - - c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data}) -} - // @Summary 获取信息系统信息 // @Produce application/json // @Accept application/json diff --git a/service/app.go b/service/app.go index d5a7ceb..ff2e0ea 100644 --- a/service/app.go +++ b/service/app.go @@ -46,7 +46,7 @@ type appStruct struct { //获取我的应用列表 func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppList { //获取docker应用 - cli, err := client2.NewClientWithOpts(client2.FromEnv) + cli, err := client2.NewClientWithOpts(client2.FromEnv, client2.WithTimeout(time.Second*5)) if err != nil { a.log.Error("初始化client失败", "app.getmylist", "line:36", err) } @@ -81,13 +81,13 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis m.Label = m.Title } - info, err := cli.ContainerInspect(context.Background(), container.ID) - var tm string - if err != nil { - tm = time.Now().String() - } else { - tm = info.State.StartedAt - } + // info, err := cli.ContainerInspect(context.Background(), container.ID) + // var tm string + // if err != nil { + // tm = time.Now().String() + // } else { + // tm = info.State.StartedAt + //} list = append(list, model2.MyAppList{ Name: m.Label, Icon: m.Icon, @@ -95,9 +95,9 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis CustomId: strings.ReplaceAll(container.Names[0], "/", ""), Port: m.PortMap, Index: m.Index, - UpTime: tm, - Image: m.Image, - Slogan: m.Slogan, + //UpTime: tm, + Image: m.Image, + Slogan: m.Slogan, //Rely: m.Rely, }) } @@ -120,7 +120,7 @@ func (a *appStruct) GetSystemAppList() *[]model2.MyAppList { fts.Add("label", "origin=system") containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts}) if err != nil { - a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err) + a.log.Error("获取docker容器失败", "app.sys", "line:123", err) } //获取本地数据库应用 @@ -179,7 +179,7 @@ func (a *appStruct) GetContainerInfo(name string) (types.Container, error) { filters.Add("name", name) containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters}) if err != nil { - a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err) + a.log.Error("获取docker容器失败", "app.getcontainerinfo", "line:182", err) } if len(containers) > 0 { diff --git a/service/casa.go b/service/casa.go index 2446ca9..2768433 100644 --- a/service/casa.go +++ b/service/casa.go @@ -2,6 +2,7 @@ package service import ( json2 "encoding/json" + "fmt" "strconv" "github.com/IceWhaleTech/CasaOS/model" @@ -12,7 +13,7 @@ import ( ) type CasaService interface { - GetServerList(index, size, tp, categoryId, key string) ([]model.ServerAppList, int64) + GetServerList(index, size, tp, categoryId, key string) (recommend, list, community []model.ServerAppList) GetServerCategoryList() []model.ServerCategoryList GetTaskList(size int) []model2.TaskDBModel GetServerAppInfo(id string) model.ServerAppList @@ -44,20 +45,34 @@ func (o *casaService) GetTaskList(size int) []model2.TaskDBModel { return list } -func (o *casaService) GetServerList(index, size, tp, categoryId, key string) ([]model.ServerAppList, int64) { +func (o *casaService) GetServerList(index, size, tp, categoryId, key string) (recommend, list, community []model.ServerAppList) { + + keyName := fmt.Sprintf("list_%s_%s_%s_%s", index, size, tp, categoryId) + + if result, ok := Cache.Get(keyName); ok { + res, ok := result.(string) + if ok { + json2.Unmarshal([]byte(gjson.Get(res, "data.list").String()), &list) + json2.Unmarshal([]byte(gjson.Get(res, "data.recommend").String()), &recommend) + json2.Unmarshal([]byte(gjson.Get(res, "data.community").String()), &community) + return + } + } head := make(map[string]string) head["Authorization"] = GetToken() - listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/app/list?index="+index+"&size="+size+"&type="+tp+"&category_id="+categoryId+"&key="+key, head) + listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/newlist?index="+index+"&size="+size+"&rank="+tp+"&category_id="+categoryId+"&key="+key, head) - list := []model.ServerAppList{} + json2.Unmarshal([]byte(gjson.Get(listS, "data.list").String()), &list) + json2.Unmarshal([]byte(gjson.Get(listS, "data.recommend").String()), &recommend) + json2.Unmarshal([]byte(gjson.Get(listS, "data.community").String()), &community) - count := gjson.Get(listS, "data.count").Int() - json2.Unmarshal([]byte(gjson.Get(listS, "data.items").String()), &list) - - return list, count + if len(list) > 0 { + Cache.SetDefault(keyName, listS) + } + return } func (o *casaService) GetServerCategoryList() []model.ServerCategoryList { @@ -65,7 +80,7 @@ func (o *casaService) GetServerCategoryList() []model.ServerCategoryList { head := make(map[string]string) head["Authorization"] = GetToken() - listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/app/category", head) + listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/category", head) list := []model.ServerCategoryList{} @@ -79,7 +94,7 @@ func (o *casaService) GetServerAppInfo(id string) model.ServerAppList { head["Authorization"] = GetToken() - infoS := httper2.Get(config.ServerInfo.ServerApi+"/v1/app/info/"+id, head) + infoS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/info/"+id, head) info := model.ServerAppList{} json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info) diff --git a/service/disk.go b/service/disk.go index cf51e1c..829c818 100644 --- a/service/disk.go +++ b/service/disk.go @@ -5,6 +5,7 @@ import ( "fmt" "strconv" "strings" + "time" "github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/pkg/config" @@ -26,7 +27,10 @@ type DiskService interface { AddPartition(path string) string GetDiskInfoByPath(path string) *disk.UsageStat MountDisk(path, volume string) - SerialAll(mountPoint string) *[]model2.SerialDisk + GetSerialAll() []model2.SerialDisk + SaveMountPoint(m model2.SerialDisk) + DeleteMountPoint(path, mountPoint string) + DeleteMount(id string) } type diskService struct { log loger2.OLog @@ -86,9 +90,21 @@ func (d *diskService) GetDiskInfoByPath(path string) *disk.UsageStat { //get disk details func (d *diskService) LSBLK() []model.LSBLKModel { + key := "system_lsblk" + + var n []model.LSBLKModel + + if result, ok := Cache.Get(key); ok { + + res, ok := result.([]model.LSBLKModel) + if ok { + return res + } + } + str := command2.ExecLSBLK() if str == nil { - d.log.Error("lsblk exec error") + d.log.Error("lsblk exec error,lsblk") return nil } var m []model.LSBLKModel @@ -97,8 +113,6 @@ func (d *diskService) LSBLK() []model.LSBLKModel { d.log.Error("json ummarshal error", err) } - var n []model.LSBLKModel - var c []model.LSBLKModel var fsused uint64 @@ -136,13 +150,16 @@ func (d *diskService) LSBLK() []model.LSBLKModel { fsused = 0 } } + if len(n) > 0 { + Cache.Add(key, n, time.Second*10) + } return n } func (d *diskService) GetDiskInfo(path string) model.LSBLKModel { str := command2.ExecLSBLKByPath(path) if str == nil { - d.log.Error("lsblk exec error") + d.log.Error("lsblk exec error,str") return model.LSBLKModel{} } var ml []model.LSBLKModel @@ -197,13 +214,25 @@ func (d *diskService) MountDisk(path, volume string) { } func (d *diskService) SaveMountPoint(m model2.SerialDisk) { - d.db.Save(&m) + d.db.Create(&m) } -func (d *diskService) SerialAll(mountPoint string) *[]model2.SerialDisk { +func (d *diskService) DeleteMount(id string) { + + d.db.Delete(&model2.SerialDisk{}).Where("id = ?", id) +} + +func (d *diskService) DeleteMountPoint(path, mountPoint string) { + + d.db.Delete(&model2.SerialDisk{}).Where("path= ? && mount_point = ?", path, mountPoint) + + command2.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;do_umount " + path) +} + +func (d *diskService) GetSerialAll() []model2.SerialDisk { var m []model2.SerialDisk d.db.Find(&m) - return &m + return m } func NewDiskService(log loger2.OLog, db *gorm.DB) DiskService { diff --git a/service/docker.go b/service/docker.go index 5bd865f..6a42f90 100644 --- a/service/docker.go +++ b/service/docker.go @@ -8,7 +8,6 @@ import ( json2 "encoding/json" "fmt" "reflect" - "regexp" "syscall" model2 "github.com/IceWhaleTech/CasaOS/service/model" @@ -366,11 +365,11 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s // if net != "host" { // portMaps[nat.Port(fmt.Sprint(m.Port)+"/tcp")] = []nat.PortBinding{{HostIP: "", HostPort: m.PortMap}} // } - port := "" + //port := "" for _, portMap := range m.Ports { - if portMap.CommendPort == m.PortMap && portMap.Protocol == "tcp" || portMap.Protocol == "both" { - port = portMap.ContainerPort - } + // if portMap.CommendPort == m.PortMap && portMap.Protocol == "tcp" || portMap.Protocol == "both" { + // port = portMap.ContainerPort + // } if portMap.Protocol == "tcp" { tContainer, _ := strconv.Atoi(portMap.ContainerPort) @@ -413,7 +412,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s var envArr []string for _, e := range m.Envs { if strings.HasPrefix(e.Value, "$") { - envArr = append(envArr, e.Name+"="+env_helper.ReplaceDefaultENV(e.Value)) + envArr = append(envArr, e.Name+"="+env_helper.ReplaceDefaultENV(e.Value, MyService.System().GetTimeZone())) continue } if len(e.Value) > 0 { @@ -443,27 +442,28 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s for _, v := range m.Volumes { path := v.Path if len(path) == 0 { - path = docker.GetDir(containerDbId, v.ContainerPath) + path = docker.GetDir(containerDbId, v.Path) if len(path) == 0 { continue } } path = strings.ReplaceAll(path, "$AppID", containerDbId) - reg1 := regexp.MustCompile(`([^<>/\\\|:""\*\?]+\.\w+$)`) - result1 := reg1.FindAllStringSubmatch(path, -1) - if len(result1) == 0 { - err = file.IsNotExistMkDir(path) - if err != nil { - ds.log.Error("mkdir error", err) - continue - } - } else { - err = file.IsNotExistCreateFile(path) - if err != nil { - ds.log.Error("mkdir error", err) - continue - } + //reg1 := regexp.MustCompile(`([^<>/\\\|:""\*\?]+\.\w+$)`) + //result1 := reg1.FindAllStringSubmatch(path, -1) + //if len(result1) == 0 { + err = file.IsNotExistMkDir(path) + if err != nil { + ds.log.Error("mkdir error", err) + continue } + //} + // else { + // err = file.IsNotExistCreateFile(path) + // if err != nil { + // ds.log.Error("mkdir error", err) + // continue + // } + // } volumes = append(volumes, mount.Mount{ Type: mount.TypeBind, @@ -479,17 +479,17 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s if len(m.Restart) > 0 { rp.Name = m.Restart } - healthTest := []string{} - if len(port) > 0 { - healthTest = []string{"CMD-SHELL", "curl -f http://localhost:" + port + m.Index + " || exit 1"} - } + // healthTest := []string{} + // if len(port) > 0 { + // healthTest = []string{"CMD-SHELL", "curl -f http://localhost:" + port + m.Index + " || exit 1"} + // } - health := &container.HealthConfig{ - Test: healthTest, - StartPeriod: 0, - Retries: 1000, - } - fmt.Print(health) + // health := &container.HealthConfig{ + // Test: healthTest, + // StartPeriod: 0, + // Retries: 1000, + // } + // fmt.Print(health) config := &container.Config{ Image: imageName, Labels: map[string]string{"origin": m.Origin, m.Origin: m.Origin}, diff --git a/service/file.go b/service/file.go new file mode 100644 index 0000000..7130cca --- /dev/null +++ b/service/file.go @@ -0,0 +1,85 @@ +package service + +import ( + "context" + "io" +) + +// type InteruptReader struct { +// r io.Reader +// interupt chan int +// } + +// func NewInteruptReader(r io.Reader) InteruptReader { +// return InteruptReader{ +// r, +// make(chan int), +// } +// } + +// func (r InteruptReader) Read(p []byte) (n int, err error) { +// if r.r == nil { +// return 0, io.EOF +// } +// select { +// case <-r.interupt: +// return r.r.Read(p) +// default: +// r.r = nil +// return 0, io.EOF +// } +// } + +// func (r InteruptReader) Cancel() { +// r.interupt <- 0 +// } + +type reader struct { + ctx context.Context + r io.Reader +} + +// NewReader wraps an io.Reader to handle context cancellation. +// +// Context state is checked BEFORE every Read. +func NewReader(ctx context.Context, r io.Reader) io.Reader { + if r, ok := r.(*reader); ok && ctx == r.ctx { + return r + } + return &reader{ctx: ctx, r: r} +} + +func (r *reader) Read(p []byte) (n int, err error) { + select { + case <-r.ctx.Done(): + return 0, r.ctx.Err() + default: + return r.r.Read(p) + } +} + +type writer struct { + ctx context.Context + w io.Writer +} + +type copier struct { + writer +} + +func NewWriter(ctx context.Context, w io.Writer) io.Writer { + if w, ok := w.(*copier); ok && ctx == w.ctx { + return w + } + return &copier{writer{ctx: ctx, w: w}} +} + +// Write implements io.Writer, but with context awareness. +func (w *writer) Write(p []byte) (n int, err error) { + select { + case <-w.ctx.Done(): + return 0, w.ctx.Err() + default: + return w.w.Write(p) + } +} diff --git a/service/file_test.go b/service/file_test.go new file mode 100644 index 0000000..3327f8b --- /dev/null +++ b/service/file_test.go @@ -0,0 +1,81 @@ +package service + +import ( + "context" + "fmt" + "io" + "log" + "os" + "testing" + "time" +) + +var ctx context.Context +var cancel context.CancelFunc + +func TestNewInteruptReader(t *testing.T) { + ctx, cancel = context.WithCancel(context.Background()) + + go func() { + // 在初始上下文的基础上创建一个有取消功能的上下文 + // ctx, cancel := context.WithCancel(ctx) + fmt.Println("开始") + fIn, err := os.Open("/Users/liangjianli/Downloads/demo_data.tar.gz") + if err != nil { + + } + defer fIn.Close() + fmt.Println("创建新文件") + fOut, err := os.Create("/Users/liangjianli/Downloads/demo_data1.tar.gz") + if err != nil { + fmt.Println(err) + } + + defer fOut.Close() + + fmt.Println("准备复制") + // _, err = io.Copy(out, NewReader(ctx, f)) + // time.Sleep(time.Second * 2) + //ctx.Done() + // cancel() + + // interrupt context after 500ms + + // interrupt context with SIGTERM (CTRL+C) + //sigs := make(chan os.Signal, 1) + //signal.Notify(sigs, os.Interrupt) + + if err != nil { + log.Fatal(err) + } + + // Reader that fails when context is canceled + in := NewReader(ctx, fIn) + // Writer that fails when context is canceled + out := NewWriter(ctx, fOut) + + //time.Sleep(2 * time.Second) + + //cancel() + + n, err := io.Copy(out, in) + log.Println(n, "bytes copied.") + if err != nil { + fmt.Println("Err:", err) + } + + fmt.Println("Closing.") + }() + + go func() { + //<-sigs + time.Sleep(time.Second) + fmt.Println("退出") + ddd() + }() + time.Sleep(time.Second * 10) +} + +func ddd() { + cancel() +} diff --git a/service/model/o_disk.go b/service/model/o_disk.go index 59e9792..20aa059 100644 --- a/service/model/o_disk.go +++ b/service/model/o_disk.go @@ -3,7 +3,7 @@ package model //SerialAdvanced Technology Attachment (STAT) type SerialDisk struct { Id uint `gorm:"column:id;primary_key" json:"id"` - DiskId string `json:"disk_id"` + Serial string `json:"serial"` Path string `json:"path"` State int `json:"state"` MountPoint string `json:"mount_point"` diff --git a/service/system.go b/service/system.go index 90c66f7..1513af5 100644 --- a/service/system.go +++ b/service/system.go @@ -16,6 +16,7 @@ type SystemService interface { GetCasaOSLogs(lineNumber int) string UpdateAssist() UpSystemPort(port string) + GetTimeZone() string } type systemService struct { log loger.OLog @@ -30,6 +31,11 @@ func (s *systemService) UpdateSystemVersion(version string) { func (s *systemService) UpdateAssist() { s.log.Error(command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/assist.sh")) } + +func (s *systemService) GetTimeZone() string { + return command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetTimeZone") +} + func (s *systemService) GetSystemConfigDebug() []string { return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetSysInfo") } diff --git a/shell/helper.sh b/shell/helper.sh index a27f87f..f072b99 100644 --- a/shell/helper.sh +++ b/shell/helper.sh @@ -30,6 +30,11 @@ GetNetCard() { fi } + +GetTimeZone(){ + timedatectl | grep "Time zone" | awk '{print $3}' +} + #查看网卡状态 #param 网卡名称 CatNetCardState() { @@ -194,7 +199,7 @@ do_mount() { eval $(blkid -o udev ${DEVICE} | grep -i -e "ID_FS_LABEL" -e "ID_FS_TYPE") LABEL=$2 - if grep -q " /media/${LABEL} " /etc/mtab; then + if grep -q " ${LABEL} " /etc/mtab; then # Already in use, make a unique one LABEL+="-${DEVBASE}" fi @@ -205,7 +210,7 @@ do_mount() { DEV_LABEL="${DEVBASE}" fi - MOUNT_POINT="/media/${DEV_LABEL}" + MOUNT_POINT="${DEV_LABEL}" ${log} "Mount point: ${MOUNT_POINT}" @@ -233,3 +238,94 @@ do_mount() { ;; esac } + +# $1=sda1 +do_umount() { + log="logger -t usb-mount.sh -s " + DEVBASE=$1 + DEVICE="${DEVBASE}" + MOUNT_POINT=$(mount | grep ${DEVICE} | awk '{ print $3 }') + + if [[ -z ${MOUNT_POINT} ]]; then + ${log} "Warning: ${DEVICE} is not mounted" + else + umount -l ${DEVICE} + ${log} "Unmounted ${DEVICE} from ${MOUNT_POINT}" + /bin/rmdir "${MOUNT_POINT}" + sed -i.bak "\@${MOUNT_POINT}@d" /var/log/usb-mount.track + fi + +} +# $1=/mnt/volume1/data.img +# $2=100G +PackageDocker() { + image=$1 + docker="/mnt/casa_docker" + #判断目录docker存在不存在则创建,存在检查是否为空 + + if [ ! -d "$docker" ]; then + mkdir ${docker} + fi + + if [ "$(ls -A $docker)" = "" ]; then + echo "$docker count is 0" + else + mkdir ${docker}_bak + mv -r ${docker} ${docker}_bak + fi + + daemon="/etc/docker/daemon.json" + #1创建img文件在挂载的目录 + fallocate -l $2 $image + #2初始化img文件 + mkfs -t ext4 $image + #3挂载img文件 + sudo mount -o loop $image $docker + #4给移动/var/lib/docker数据到img挂载的目录 + systemctl stop docker.socket + systemctl stop docker + cp -r /var/lib/docker/* ${docker}/ + #5在/etc/docker写入daemon.json(需要检查) + if [ -d "$daemon" ]; then + mv -r $daemon ${daemon}.bak + fi + echo "{\"data-root\": \"$docker\"}" >$daemon + #删除老数据腾出空间 + #rm -fr /var/lib/docker + systemctl start docker.socket + systemctl start docker +} + +DockerImgMove() { + image=$1 + systemctl stop docker.socket + systemctl stop docker + sudo umount -f $image +} + +GetDockerDataRoot() { + docker info | grep "Docker Root Dir:" +} + +SetLink() { + ln -s /mnt/casa_sda1/AppData /DATA/AppData + #删除所有软链 + find /DATA -type l -delete +} + +#压缩文件夹 + +TarFolder() { + #压缩 + tar -zcvf data.tar.gz -C/DATA/ AppDataBak/ + + #解压 + tar zxvf data.tar.gz + + #查看某文件夹下的所有包括子文件夹文件 + ls /DATA/Media -lR | grep "^-" | wc -l + # ls -lR|grep "^d"| wc -l 查看某个文件夹下文件夹的个数,包括子文件夹下的文件夹个数。 + + #查看固定文件夹大小 + du -sh /DATA +} diff --git a/types/system.go b/types/system.go index 513c250..fc30d4d 100644 --- a/types/system.go +++ b/types/system.go @@ -1,4 +1,4 @@ package types -const CURRENTVERSION = "0.2.3" -const BODY = "
  • Add detailed CPU and memory statistics.
  • Add the multi-language function and add Chinese translation.
  • Add the function to modify the search engine.
  • Add the function of modifying the WebUI port
  • fixed some bugs
  • Preprocessing usb automounting
  • Update update script
  • " +const CURRENTVERSION = "0.2.4" +const BODY = "
  • New App Store
  • Fix minor bugs
  • "