Use a .new temp file while gathering info, only move it into place on success
This commit is contained in:
33
src/ssh.go
33
src/ssh.go
@ -209,29 +209,34 @@ func (rb *RouterBackup) BackupCommands(commands []string, outputDir string) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
filename := rb.hostname
|
filename := rb.hostname
|
||||||
filepath := filepath.Join(outputDir, filename)
|
finalPath := filepath.Join(outputDir, filename)
|
||||||
|
tempPath := finalPath + ".new"
|
||||||
|
|
||||||
// Truncate file at start
|
// Create temporary file
|
||||||
file, err := os.Create(filepath)
|
file, err := os.Create(tempPath)
|
||||||
if err != nil {
|
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()
|
file.Close()
|
||||||
|
|
||||||
successCount := 0
|
successCount := 0
|
||||||
|
hasErrors := false
|
||||||
|
|
||||||
for i, command := range commands {
|
for i, command := range commands {
|
||||||
fmt.Printf("Running command %d/%d: %s\n", i+1, len(commands), command)
|
fmt.Printf("Running command %d/%d: %s\n", i+1, len(commands), command)
|
||||||
output, err := rb.RunCommand(command)
|
output, err := rb.RunCommand(command)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error executing '%s': %v\n", command, err)
|
fmt.Printf("Error executing '%s': %v\n", command, err)
|
||||||
|
hasErrors = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append to file
|
// Append to temporary file
|
||||||
file, err := os.OpenFile(filepath, os.O_APPEND|os.O_WRONLY, 0644)
|
file, err := os.OpenFile(tempPath, os.O_APPEND|os.O_WRONLY, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to open file for writing: %v\n", err)
|
fmt.Printf("Failed to open file for writing: %v\n", err)
|
||||||
|
hasErrors = true
|
||||||
continue
|
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))
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user