postgresqlbashdockerpg-dump

docker exec pg_dump in bash function


I'm trying to run pg_dump in a docker container, in a bash function, but I'm getting an error can't create : nonexistent directory. The dir does exist, so I suspect that the output redirection (>) is trying to run on the host system when running inside the function. When I run the command outside of the bash function it works.

Note that the psql container has the directory /var/lib/postgresql/backups/ mapped to /usr/share/postgresql/backups/ on the host.

The command that works is,

docker exec -it psql sh -c 'pg_dump -U $PG_USER MY_TABLE > /var/lib/postgresql/backups/my_table.sql

The function that is not working

# @param $1 -- the name of the table to export
# @param $2 -- the filename to export the table to
function backup_table() {
  local table_name="$1"
  local output_path="/var/lib/postgresql/backups/$2"
  docker exec -it psql sh -c 'pg_dump -U "$PG_USER" $table_name > $output_path'
}
backup_table MY_TABLE my_table.sql

Solution

  • The redirection is properly happening inside the container -- but output_path isn't being passed there.


    Assuming PG_USER is defined inside the container:

    backup_table() {                    # POSIX function syntax
      local table_name output_path cmd  # declare all our locals at once
      table_name="$1"
      output_path="/var/lib/postgresql/backups/$2"
    
      # Bash extension, compatible through older releases: substitute
      # escaped values in place of %q placeholders into $cmd
      printf -v cmd 'pg_dump -U "$PG_USER" %q >%q' "$table_name" "$output_path"
      docker exec -it psql bash -c "$cmd"
    }
    backup_table MY_TABLE my_table.sql
    

    Note:

    If you only need to support bash 5.0 or newer, you could replace the printf command with:

    cmd='pg_dump -U "$PG_USER" '"${table_name@Q}"' >'"${output_path@Q}"