From 67ff8ceca9a4b49de87bbb9f5e13dabefe0e6253 Mon Sep 17 00:00:00 2001 From: Melanie Plageman Date: Thu, 30 Apr 2026 16:06:06 -0400 Subject: [PATCH] Put pg_combinebackup debug test output in temp file Having --debug as the default option to pg_combinebackup in init_from_backup() makes the logs extremely verbose. It is used for debugging failures, so put the output in a temp file and only keep it around if tests fail. Author: Melanie Plageman Reviewed-by: Robert Haas Disussion: https://postgr.es/m/y73coty2smkxgvelh4e32kqrt5pyn2pb7cz7x4mrz6yaxitqd5%40nzhkeazqf4bn Backpatch-through: 17 --- src/test/perl/PostgreSQL/Test/Cluster.pm | 86 +++++++++++++++++++++++- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm index 529f49efee1..0d4fd929b6b 100644 --- a/src/test/perl/PostgreSQL/Test/Cluster.pm +++ b/src/test/perl/PostgreSQL/Test/Cluster.pm @@ -125,6 +125,7 @@ our $min_compat = 12; # list of file reservations made by get_free_port my @port_reservation_files; +my @combinebackup_debug_logs; # We want to choose a server port above the range that servers typically use # on Unix systems and below the range those systems typically use for ephemeral @@ -924,7 +925,9 @@ pathnames that should be used for the target cluster. To restore from an incremental backup, pass the parameter combine_with_prior as a reference to an array of prior backup names with which this backup -is to be combined using pg_combinebackup. +is to be combined using pg_combinebackup. pg_combinebackup is run with +--debug, but the output is captured in a temporary file and only copied to the +test log if pg_combinebackup fails or if a later test fails. Streaming replication can be enabled on this node by passing the keyword parameter has_streaming => 1. This is disabled by default. @@ -990,7 +993,7 @@ sub init_from_backup } push @combineargs, @prior_backup_path, $backup_path, '--output' => $data_path; - PostgreSQL::Test::Utils::system_or_bail(@combineargs); + $self->_run_pg_combinebackup_with_debug_log(@combineargs); } elsif (defined $params{tar_program}) { @@ -1105,6 +1108,85 @@ port = $port return; } +sub _run_pg_combinebackup_with_debug_log +{ + my ($self, @cmd) = @_; + my $debug_log = $self->basedir . '/pg_combinebackup_debug.log'; + + print("# Running: " . join(" ", @cmd) . "\n"); + # If this pg_combinebackup invocation itself fails, print its captured + # output immediately. Successful invocations may still be printed later if + # some subsequent TAP assertion in this test script fails. + if (!IPC::Run::run(\@cmd, '&>' => $debug_log)) + { + _print_pg_combinebackup_debug_log($debug_log); + + if ($? == -1) + { + BAIL_OUT( + sprintf( + "failed to execute command \"%s\": $!", join(" ", @cmd))); + } + elsif ($? & 127) + { + BAIL_OUT( + sprintf( + "command \"%s\" died with signal %d", + join(" ", @cmd), $? & 127)); + } + else + { + BAIL_OUT( + sprintf( + "command \"%s\" exited with value %d", + join(" ", @cmd), $? >> 8)); + } + } + + # pg_combinebackup succeeded. Retain its debug log so that, if a later TAP + # assertion in this test fails, the END block can print the combine step + # that produced the restored state; on a clean run the END block removes it. + # On failure above we already printed the log and bailed out, so it is + # deliberately not added to the list here (which also avoids printing it + # twice). + push @combinebackup_debug_logs, $debug_log; +} + +sub _print_pg_combinebackup_debug_log +{ + my ($debug_log) = @_; + + return unless -e $debug_log; + + diag("pg_combinebackup debug output from $debug_log:\n" . + PostgreSQL::Test::Utils::slurp_file($debug_log)); +} + +# Keep pg_combinebackup debug logs until test exit. If pg_combinebackup itself +# fails, its log is printed at the failure site above. If pg_combinebackup +# succeeds but a later TAP assertion fails, print the retained logs here so the +# regress output includes the combine step that produced the restored state. +# Remove the logs after a clean run. +END +{ + # take care not to change the script's exit value + my $exit_code = $?; + + if ($exit_code == 0 && PostgreSQL::Test::Utils::all_tests_passing()) + { + unlink @combinebackup_debug_logs; + } + else + { + foreach my $debug_log (@combinebackup_debug_logs) + { + _print_pg_combinebackup_debug_log($debug_log); + } + } + + $? = $exit_code; +} + =pod =item $node->rotate_logfile() -- 2.47.3