diff --git a/etcdserver/server.go b/etcdserver/server.go index 0733fd285473..1638719ffc66 100644 --- a/etcdserver/server.go +++ b/etcdserver/server.go @@ -25,6 +25,7 @@ import ( "os" "path" "regexp" + "strings" "sync" "sync/atomic" "time" @@ -323,6 +324,17 @@ func NewServer(cfg ServerConfig) (srv *EtcdServer, err error) { plog.Fatalf("create snapshot directory error: %v", 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() diff --git a/pkg/fileutil/fileutil.go b/pkg/fileutil/fileutil.go index f36136182b9e..2bafa2a82ee1 100644 --- a/pkg/fileutil/fileutil.go +++ b/pkg/fileutil/fileutil.go @@ -127,3 +127,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/pkg/fileutil/fileutil_test.go b/pkg/fileutil/fileutil_test.go index 7cfac190e5c0..fd0df2fac515 100644 --- a/pkg/fileutil/fileutil_test.go +++ b/pkg/fileutil/fileutil_test.go @@ -166,3 +166,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") + } +}