From 195024e505746ce9eb096422352762619b8fd429 Mon Sep 17 00:00:00 2001 From: Jakub Jirutka Date: Fri, 14 Apr 2023 16:11:42 +0200 Subject: [PATCH] Fix psql_command and pg_restore_command to accept command with arguments These commands are executed without `shell=True`, so the subprocess module treats e.g. "docker exec my_pg_container psql" as a single command (resulting in Errno 2 "No such file or directory") instead of a command with arguments. --- borgmatic/hooks/postgresql.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/borgmatic/hooks/postgresql.py b/borgmatic/hooks/postgresql.py index 1235d60..fbe890a 100644 --- a/borgmatic/hooks/postgresql.py +++ b/borgmatic/hooks/postgresql.py @@ -1,6 +1,7 @@ import csv import logging import os +import shlex from borgmatic.execute import ( execute_command, @@ -59,9 +60,10 @@ def database_names_to_dump(database, extra_environment, log_prefix, dry_run): if dry_run: return () - psql_command = database.get('psql_command') or 'psql' + psql_command = shlex.split(database.get('psql_command') or 'psql') list_command = ( - (psql_command, '--list', '--no-password', '--no-psqlrc', '--csv', '--tuples-only') + tuple(psql_command) + + ('--list', '--no-password', '--no-psqlrc', '--csv', '--tuples-only') + (('--host', database['hostname']) if 'hostname' in database else ()) + (('--port', str(database['port'])) if 'port' in database else ()) + (('--username', database['username']) if 'username' in database else ()) @@ -203,9 +205,10 @@ def restore_database_dump(database_config, log_prefix, location_config, dry_run, dump_filename = dump.make_database_dump_filename( make_dump_path(location_config), database['name'], database.get('hostname') ) - psql_command = database.get('psql_command') or 'psql' + psql_command = shlex.split(database.get('psql_command') or 'psql') analyze_command = ( - (psql_command, '--no-password', '--no-psqlrc', '--quiet') + tuple(psql_command) + + ('--no-password', '--no-psqlrc', '--quiet') + (('--host', database['hostname']) if 'hostname' in database else ()) + (('--port', str(database['port'])) if 'port' in database else ()) + (('--username', database['username']) if 'username' in database else ()) @@ -213,9 +216,10 @@ def restore_database_dump(database_config, log_prefix, location_config, dry_run, + (tuple(database['analyze_options'].split(' ')) if 'analyze_options' in database else ()) + ('--command', 'ANALYZE') ) - pg_restore_command = database.get('pg_restore_command') or 'pg_restore' + pg_restore_command = shlex.split(database.get('pg_restore_command') or 'pg_restore') restore_command = ( - (psql_command if all_databases else pg_restore_command, '--no-password') + tuple(psql_command if all_databases else pg_restore_command) + + ('--no-password',) + ( ('--if-exists', '--exit-on-error', '--clean', '--dbname', database['name']) if not all_databases