diff --git a/SQLBackupToCOS/BackupService.cs b/SQLBackupToCOS/BackupService.cs index 3ee94cf..ae4ead4 100644 --- a/SQLBackupToCOS/BackupService.cs +++ b/SQLBackupToCOS/BackupService.cs @@ -74,10 +74,10 @@ public class BackupService(ILogger logger, IConfiguration config, using var proc = Process.Start(psi) ?? throw new InvalidOperationException("Failed to start mysqldump"); await using var fs = new FileStream(dumpFile, FileMode.CreateNew, FileAccess.Write, FileShare.None); - + var copyTask = proc.StandardOutput.BaseStream.CopyToAsync(fs, 81920, ct); var stderrTask = ConsumeStreamToLoggerAsync(proc.StandardError, _logger, ct); - + await Task.WhenAll(copyTask, stderrTask); await proc.WaitForExitAsync(ct); @@ -92,9 +92,9 @@ public class BackupService(ILogger logger, IConfiguration config, } _logger.LogInformation("Compressing backup directory to {File}", finalDump); - + await CompressDirectoryAsync([dumpDir, extraDir], finalDump, ct); - + Directory.Delete(dumpDir, recursive: true); _logger.LogInformation("Backup completed: {File}", finalDump); @@ -111,8 +111,9 @@ public class BackupService(ILogger logger, IConfiguration config, { // 构建 tar 命令参数 // tar -czf output.tar.gz -C /parent1 folder1 -C /parent2 folder2 - var args = new StringBuilder($"-czf {targetFile}"); - + // --ignore-failed-read: 忽略无法读取的文件,继续备份 + var args = new StringBuilder($"-czf {targetFile} --ignore-failed-read"); + foreach (var sourceDir in sourceDirs) { if (Directory.Exists(sourceDir)) @@ -143,10 +144,18 @@ public class BackupService(ILogger logger, IConfiguration config, await stderrTask; await proc.WaitForExitAsync(ct); - if (proc.ExitCode != 0) + // tar 返回码说明: + // 0 = 成功 + // 1 = 一些文件有问题,但备份继续(使用 --ignore-failed-read 时) + // 2 = 致命错误 + if (proc.ExitCode > 1) { throw new InvalidOperationException($"tar exited with code {proc.ExitCode}"); } + else if (proc.ExitCode == 1) + { + _logger.LogWarning("tar completed with warnings (exit code 1), some files may have been skipped"); + } } private async Task ConsumeStreamToLoggerAsync(StreamReader err, ILogger log, CancellationToken ct)