| 177 | } |
| 178 | |
| 179 | func (r *Remote) Backup(info BackupInfo) error { |
| 180 | if cmd.CheckIllegal(r.Password, r.Address, r.User, info.Name) { |
| 181 | return buserr.New("ErrCmdIllegal") |
| 182 | } |
| 183 | imageTag, err := loadImageTag(info.Database) |
| 184 | if err != nil { |
| 185 | return err |
| 186 | } |
| 187 | info.Task.Log(i18n.GetWithName("RemoteBackup", imageTag)) |
| 188 | fileOp := files.NewFileOp() |
| 189 | if !fileOp.Stat(info.TargetDir) { |
| 190 | if err := os.MkdirAll(info.TargetDir, os.ModePerm); err != nil { |
| 191 | return fmt.Errorf("mkdir %s failed, err: %v", info.TargetDir, err) |
| 192 | } |
| 193 | } |
| 194 | fileNameItem := info.TargetDir + "/" + strings.TrimSuffix(info.FileName, ".gz") |
| 195 | backupFile, err := os.OpenFile(fileNameItem, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) |
| 196 | if err != nil { |
| 197 | return err |
| 198 | } |
| 199 | backupFileClosed := false |
| 200 | defer func() { |
| 201 | if !backupFileClosed { |
| 202 | _ = backupFile.Close() |
| 203 | } |
| 204 | }() |
| 205 | backupCommand := exec.Command( |
| 206 | "docker", |
| 207 | "run", "--rm", "--net=host", "-i", |
| 208 | "-e", "PGPASSWORD="+r.Password, |
| 209 | imageTag, |
| 210 | "pg_dump", |
| 211 | "-h", r.Address, |
| 212 | "-p", fmt.Sprintf("%d", r.Port), |
| 213 | "--no-owner", |
| 214 | "-Fc", |
| 215 | "-U", r.User, |
| 216 | info.Name, |
| 217 | ) |
| 218 | backupCommand.Stdout = backupFile |
| 219 | stderr := &limitedBuffer{limit: maxPgDumpStderrCapture} |
| 220 | backupCommand.Stderr = stderr |
| 221 | if err := backupCommand.Run(); err != nil { |
| 222 | return fmt.Errorf("backup failed, stderr: %s, err: %v", strings.TrimSpace(stderr.String()), err) |
| 223 | } |
| 224 | if err := backupFile.Close(); err != nil { |
| 225 | return fmt.Errorf("close backup file failed, err: %v", err) |
| 226 | } |
| 227 | backupFileClosed = true |
| 228 | |
| 229 | b := make([]byte, len(pgDumpMagic)) |
| 230 | handle, err := os.OpenFile(fileNameItem, os.O_RDONLY, os.ModePerm) |
| 231 | if err != nil { |
| 232 | return fmt.Errorf("backup file not found,err:%v", err) |
| 233 | } |
| 234 | defer handle.Close() |
| 235 | if _, err := io.ReadFull(handle, b); err != nil { |
| 236 | return fmt.Errorf("read backup header failed, stderr: %s, err: %v", strings.TrimSpace(stderr.String()), err) |