diff --git a/agent/app/service/file.go b/agent/app/service/file.go index 5b64500b1a91..a8a154d77b52 100644 --- a/agent/app/service/file.go +++ b/agent/app/service/file.go @@ -315,19 +315,18 @@ func (f *FileService) ChangeMode(op request.FileCreate) error { func (f *FileService) BatchChangeModeAndOwner(op request.FileRoleReq) error { fo := files.NewFileOp() - for _, path := range op.Paths { - if !fo.Stat(path) { + for _, p := range op.Paths { + if !fo.Stat(p) { return buserr.New("ErrPathNotFound") } - if err := fo.ChownR(path, op.User, op.Group, op.Sub); err != nil { - return err - } - if err := fo.ChmodR(path, op.Mode, op.Sub); err != nil { - return err - } + } + if err := fo.ChownRPaths(op.Paths, op.User, op.Group, op.Sub); err != nil { + return err + } + if err := fo.ChmodRPaths(op.Paths, op.Mode, op.Sub); err != nil { + return err } return nil - } func (f *FileService) ChangeOwner(req request.FileRoleUpdate) error { diff --git a/agent/utils/files/file_op.go b/agent/utils/files/file_op.go index 558ce9a01054..34b93c5fdbbb 100644 --- a/agent/utils/files/file_op.go +++ b/agent/utils/files/file_op.go @@ -33,6 +33,11 @@ import ( "github.com/spf13/afero" ) +const ( + cmdDefaultTimeout = 10 * time.Second + cmdRecursiveTimeout = 5 * time.Minute +) + var protectedPaths = []string{ "/", "/bin", @@ -222,7 +227,11 @@ func (f FileOp) ChownR(dst string, uid string, gid string, sub bool) error { if sub { cmdStr = fmt.Sprintf(`chown -R %s:%s "%s"`, uid, gid, dst) } - cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(10 * time.Second)) + timeout := cmdDefaultTimeout + if sub { + timeout = cmdRecursiveTimeout + } + cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(timeout)) if err := cmdMgr.RunBashC(cmdStr); err != nil { return err } @@ -234,7 +243,11 @@ func (f FileOp) ChmodR(dst string, mode int64, sub bool) error { if sub { cmdStr = fmt.Sprintf(`%s chmod -R %v "%s"`, cmd.SudoHandleCmd(), fmt.Sprintf("%04o", mode), dst) } - cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(10 * time.Second)) + timeout := cmdDefaultTimeout + if sub { + timeout = cmdRecursiveTimeout + } + cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(timeout)) if err := cmdMgr.RunBashC(cmdStr); err != nil { return err } @@ -246,7 +259,70 @@ func (f FileOp) ChmodRWithMode(dst string, mode fs.FileMode, sub bool) error { if sub { cmdStr = fmt.Sprintf(`%s chmod -R %v "%s"`, cmd.SudoHandleCmd(), fmt.Sprintf("%o", mode.Perm()), dst) } - cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(10 * time.Second)) + timeout := cmdDefaultTimeout + if sub { + timeout = cmdRecursiveTimeout + } + cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(timeout)) + if err := cmdMgr.RunBashC(cmdStr); err != nil { + return err + } + return nil +} + +func (f FileOp) ChownRPaths(paths []string, uid string, gid string, sub bool) error { + if len(paths) == 0 { + return nil + } + if len(paths) == 1 { + return f.ChownR(paths[0], uid, gid, sub) + } + quoted := make([]string, len(paths)) + for i, p := range paths { + quoted[i] = fmt.Sprintf(`"%s"`, p) + } + args := strings.Join(quoted, " ") + var cmdStr string + if sub { + cmdStr = fmt.Sprintf(`chown -R %s:%s %s`, uid, gid, args) + } else { + cmdStr = fmt.Sprintf(`%s chown %s:%s %s`, cmd.SudoHandleCmd(), uid, gid, args) + } + timeout := cmdDefaultTimeout + if sub { + timeout = cmdRecursiveTimeout + } + cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(timeout)) + if err := cmdMgr.RunBashC(cmdStr); err != nil { + return err + } + return nil +} + +func (f FileOp) ChmodRPaths(paths []string, mode int64, sub bool) error { + if len(paths) == 0 { + return nil + } + if len(paths) == 1 { + return f.ChmodR(paths[0], mode, sub) + } + quoted := make([]string, len(paths)) + for i, p := range paths { + quoted[i] = fmt.Sprintf(`"%s"`, p) + } + args := strings.Join(quoted, " ") + modeStr := fmt.Sprintf("%04o", mode) + var cmdStr string + if sub { + cmdStr = fmt.Sprintf(`%s chmod -R %s %s`, cmd.SudoHandleCmd(), modeStr, args) + } else { + cmdStr = fmt.Sprintf(`%s chmod %s %s`, cmd.SudoHandleCmd(), modeStr, args) + } + timeout := cmdDefaultTimeout + if sub { + timeout = cmdRecursiveTimeout + } + cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(timeout)) if err := cmdMgr.RunBashC(cmdStr); err != nil { return err } diff --git a/frontend/src/api/modules/files.ts b/frontend/src/api/modules/files.ts index 9b372ba3a689..10f0db87235c 100644 --- a/frontend/src/api/modules/files.ts +++ b/frontend/src/api/modules/files.ts @@ -39,7 +39,7 @@ export const batchDeleteFile = (form: File.FileBatchDelete) => { }; export const changeFileMode = (form: File.FileCreate) => { - return http.post('files/mode', form); + return http.post('files/mode', form, TimeoutEnum.T_5M); }; export const compressFile = (form: File.FileCompress) => { @@ -148,7 +148,7 @@ export const removeFavorite = (id: number) => { }; export const batchChangeRole = (params: File.FileRole) => { - return http.post('files/batch/role', params); + return http.post('files/batch/role', params, TimeoutEnum.T_5M); }; export const getRecycleStatus = () => {