diff --git a/client/pkg/fileutil/fileutil.go b/client/pkg/fileutil/fileutil.go index f4b1986424d..85a9842b0d8 100644 --- a/client/pkg/fileutil/fileutil.go +++ b/client/pkg/fileutil/fileutil.go @@ -135,3 +135,35 @@ func CheckDirPermission(dir string, perm os.FileMode) error { } return nil } + +// RemoveMatchFile deletes file if matchFunc is true on an existing dir +// Returns error if the dir does not exist or remove file fail +func RemoveMatchFile(lg *zap.Logger, dir string, matchFunc func(fileName string) bool) error { + if lg == nil { + lg = zap.NewNop() + } + if !Exist(dir) { + return fmt.Errorf("directory %s does not exist", dir) + } + fileNames, err := ReadDir(dir) + if err != nil { + return err + } + var removeFailedFiles []string + for _, fileName := range fileNames { + if matchFunc(fileName) { + file := filepath.Join(dir, fileName) + if err = os.Remove(file); err != nil { + removeFailedFiles = append(removeFailedFiles, fileName) + lg.Error("remove file failed", + zap.String("file", file), + zap.Error(err)) + continue + } + } + } + if len(removeFailedFiles) != 0 { + return fmt.Errorf("remove file(s) %v error", removeFailedFiles) + } + return nil +} diff --git a/client/pkg/fileutil/fileutil_test.go b/client/pkg/fileutil/fileutil_test.go index 33b39a23aab..3a761ff9a7f 100644 --- a/client/pkg/fileutil/fileutil_test.go +++ b/client/pkg/fileutil/fileutil_test.go @@ -26,6 +26,8 @@ import ( "strings" "testing" "time" + + "go.uber.org/zap/zaptest" ) func TestIsDirWriteable(t *testing.T) { @@ -192,3 +194,45 @@ func TestDirPermission(t *testing.T) { t.Errorf("expected error, got nil") } } + +func TestRemoveMatchFile(t *testing.T) { + tmpdir := t.TempDir() + defer os.RemoveAll(tmpdir) + f, err := ioutil.TempFile(tmpdir, "tmp") + if err != nil { + t.Fatal(err) + } + f.Close() + f, err = ioutil.TempFile(tmpdir, "foo.tmp") + if err != nil { + t.Fatal(err) + } + f.Close() + + err = RemoveMatchFile(zaptest.NewLogger(t), tmpdir, func(fileName string) bool { + return strings.HasPrefix(fileName, "tmp") + }) + if err != nil { + t.Errorf("expected nil, got error") + } + fnames, err := ReadDir(tmpdir) + if err != nil { + t.Fatal(err) + } + if len(fnames) != 1 { + t.Errorf("expected exist 1 files, got %d", len(fnames)) + } + + f, err = ioutil.TempFile(tmpdir, "tmp") + if err != nil { + t.Fatal(err) + } + f.Close() + err = RemoveMatchFile(zaptest.NewLogger(t), tmpdir, func(fileName string) bool { + os.Remove(filepath.Join(tmpdir, fileName)) + return strings.HasPrefix(fileName, "tmp") + }) + if err == nil { + t.Errorf("expected error, got nil") + } +} diff --git a/server/etcdserver/server.go b/server/etcdserver/server.go index 71016e9f7cf..7a1aaad5fee 100644 --- a/server/etcdserver/server.go +++ b/server/etcdserver/server.go @@ -26,6 +26,7 @@ import ( "path" "regexp" "strconv" + "strings" "sync" "sync/atomic" "time" @@ -337,6 +338,17 @@ func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) { zap.Error(err), ) } + + if err = fileutil.RemoveMatchFile(cfg.Logger, cfg.SnapDir(), func(fileName string) bool { + return strings.HasPrefix(fileName, "tmp") + }); err != nil { + cfg.Logger.Error( + "failed to remove temp file(s) in snapshot directory", + zap.String("path", cfg.SnapDir()), + zap.Error(err), + ) + } + ss := snap.New(cfg.Logger, cfg.SnapDir()) bepath := cfg.BackendPath()