Use a .new temp file while gathering info, only move it into place on success

This commit is contained in:
Pim van Pelt
2025-07-06 22:43:33 +02:00
parent f05124b703
commit 7f6b030b31

View File

@ -209,29 +209,34 @@ func (rb *RouterBackup) BackupCommands(commands []string, outputDir string) erro
}
filename := rb.hostname
filepath := filepath.Join(outputDir, filename)
finalPath := filepath.Join(outputDir, filename)
tempPath := finalPath + ".new"
// Truncate file at start
file, err := os.Create(filepath)
// Create temporary file
file, err := os.Create(tempPath)
if err != nil {
return fmt.Errorf("failed to create file %s: %v", filepath, err)
return fmt.Errorf("failed to create temporary file %s: %v", tempPath, err)
}
file.Close()
successCount := 0
hasErrors := false
for i, command := range commands {
fmt.Printf("Running command %d/%d: %s\n", i+1, len(commands), command)
output, err := rb.RunCommand(command)
if err != nil {
fmt.Printf("Error executing '%s': %v\n", command, err)
hasErrors = true
continue
}
// Append to file
file, err := os.OpenFile(filepath, os.O_APPEND|os.O_WRONLY, 0644)
// Append to temporary file
file, err := os.OpenFile(tempPath, os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
fmt.Printf("Failed to open file for writing: %v\n", err)
hasErrors = true
continue
}
@ -243,9 +248,21 @@ func (rb *RouterBackup) BackupCommands(commands []string, outputDir string) erro
}
fmt.Printf("Summary: %d/%d commands successful\n", successCount, len(commands))
if successCount > 0 {
fmt.Printf("Output saved to %s\n", filepath)
if hasErrors || successCount == 0 {
// Remove .new suffix and log error
if err := os.Remove(tempPath); err != nil {
fmt.Printf("Failed to remove temporary file %s: %v\n", tempPath, err)
}
return fmt.Errorf("device backup incomplete due to command failures")
}
// All commands succeeded, move file into place atomically
if err := os.Rename(tempPath, finalPath); err != nil {
return fmt.Errorf("failed to move temporary file to final location: %v", err)
}
fmt.Printf("Output saved to %s\n", finalPath)
return nil
}