Как передать пароль в pg_dump?

294

Я пытаюсь создать cronjob для резервного копирования базы данных каждую ночь, прежде чем случится что-то катастрофическое. Похоже, эта команда должна соответствовать моим потребностям:

0 3 * * * pg_dump dbname | gzip > ~/backup/db/$(date +%Y-%m-%d).psql.gz

За исключением того, что после запуска, он ожидает, что я наберу пароль. Я не могу этого сделать, если я запускаю его из cron. Как я могу передать один автоматически?

mpen
источник
возможно полезный пост я написал об автоматизации pg_restore! medium.com/@trinity/...
kittyminky
ответьте здесь, используя строку подключения: stackoverflow.com/a/29101292/1579667
Бендж,

Ответы:

304

Создайте .pgpassфайл в домашнем каталоге учетной записи, которая pg_dumpбудет работать как. См. Документацию Postgresql libpq-pgpass для получения подробной информации о формате (включая последний абзац, где объясняется, что он будет игнорироваться, если вы не установите режим в 0600).

araqnid
источник
99
Создайте ~ / .pgpass с localhost: 5432: mydbname: postgres: mypass Затем chmod 600 ~ / .pgpass
Мирча
6
Возможно, полезно: в Ubuntu «sudo su postgres» переключиться на пользователя «postgres», затем создать файл .pgpass и выполнить дамп.
Fivedogit
1
Я проследил за вашим ответом, но все еще не смог создать файл резервной копии. Пожалуйста, смотрите мою ссылку: unix.stackexchange.com/questions/257898/… . Спасибо.
Алиссаэлия
Работает на 9.6.2: о)
Андрей
2
Примечание о sudo su postgresтом, что пользователь Unix не обязательно существует. Это не нужно. Но пользователь БД должен.
Фабьен Хаддади
217

Или вы можете настроить crontab для запуска скрипта. Внутри этого скрипта вы можете установить переменную окружения следующим образом: export PGPASSWORD="$put_here_the_password"

Таким образом, если у вас есть несколько команд, для которых требуется пароль, вы можете поместить их все в сценарий. Если пароль меняется, вам нужно изменить его только в одном месте (сценарий).

И я согласен с Джошуа, используя pg_dump -Fcгенерирует наиболее гибкий формат экспорта и уже сжат. Для получения дополнительной информации см. Документацию pg_dump.

Например

# dump the database in custom-format archive
pg_dump -Fc mydb > db.dump

# restore the database
pg_restore -d newdb db.dump
Максимум
источник
3
это не идеально. бросив его, .pgpassвы сохраните все в одном месте, без добавления дополнительного слоя косвенности. плюс, если бы все, что я хотел сделать с экспортом переменной, я сделал бы это в своем .bashrcфайле, или что бы то ни было.
mpen
9
Я понимаю, почему .pgpassфайл будет лучшим решением. Я просто давал альтернативу, не уверен, что она заслуживает понижения, хотя :)
Макс
13
Я не понизил. Это был кто-то еще; Я тоже не думал, что это оправдывает отрицательное мнение. Имейте +1, чтобы восполнить это.
mpen
7
Так много ненавистников. Я ценю этот ответ и принимаю его для собственного заявления.
Джеймс Т Снелл
8
Установка переменной среды PGPASSWORD не рекомендуется в документации ( postgresql.org/docs/current/static/libpq-envars.html ): использование этой переменной среды не рекомендуется по соображениям безопасности, поскольку некоторые операционные системы допускают пользователи root могут видеть переменные среды процесса через ps; вместо этого рассмотрите возможность использования файла ~ / .pgpass
bouchon
175

Если вы хотите сделать это одной командой:

PGPASSWORD="mypass" pg_dump mydb > mydb.dump
gitaarik
источник
27
Установка переменной среды PGPASSWORD не рекомендуется в документации ( postgresql.org/docs/current/static/libpq-envars.html ): использование этой переменной среды не рекомендуется по соображениям безопасности, поскольку некоторые операционные системы допускают пользователи root могут видеть переменные среды процесса через ps; вместо этого рассмотрите возможность использования файла ~ / .pgpass
bouchon
18
Это все еще полезный комментарий. Есть много случаев развертывания, где это все еще полезно.
Иан Дункан
1
Я всегда получал сообщение об ошибке «Ошибка аутентификации равноправного пользователя« username »». Решение было: PGPASSWORD = "mypass" pg_dump -U имя пользователя -h localhost> mydb.dump
Мартин Пабст,
4
Мое мнение таково, что гораздо лучше настроить переменную среды (где у вас есть контроль, где и как будет храниться пароль), как в известном незашифрованном месте. Эта часть документа postgresql ошибочна, и этот ответ является хорошим.
Петер - Восстановить Монику
1
В моем пароле был символ @. Это сработало. Я не мог понять, как заставить его работать с postgres://синтаксисом. Не пробовал, .pgpassпотому что у моего пользователя postgress нет домашнего каталога.
Jmathew
136

Для однострочников, таких как миграция базы данных, вы можете использовать --dbnameстроку подключения (включая пароль), как указано в руководстве по pg_dump

По сути.

pg_dump --dbname=postgresql://username:password@127.0.0.1:5432/mydatabase

Примечание. Убедитесь, что вы используете опцию --dbnameвместо более короткой -dи используете действительный префикс URI, postgresql://или postgres://.

Общая форма URI:

postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]

Лучшая практика в вашем случае (повторяющаяся задача в cron) не должна выполняться из-за проблем безопасности. Если бы не .pgpassфайл, я бы сохранил строку подключения как переменную окружения.

export MYDB=postgresql://username:password@127.0.0.1:5432/mydatabase

тогда есть в вашем crontab

0 3 * * * pg_dump --dbname=$MYDB | gzip > ~/backup/db/$(date +%Y-%m-%d).psql.gz

Хосе Александр Ибарра
источник
Версия 9.1 Postgre выводит неизвестную опцию для dbname
akohout
Это было проверено с версиями 9.4 и 9.3 на арке и RHEL соответственно. Вы можете опубликовать свою строку подключения? Анонимные конечно.
Хосе Александр Ибарра
Спасибо, @JosueIbarra. Успешно протестирован на PostgreSQL 9.3, Ubuntu 14.04.
Цао Минь Ту
1
@EntryLevelR вам нужно передать вывод в файл, чтобы сохранить его. см. этот соответствующий вопрос askubuntu.com/questions/420981/…
Хосе Александр Ибарра
4
это должен быть принятый ответ. Один лайнер, понятно.
swdev
48
$ PGPASSWORD="mypass" pg_dump -i -h localhost -p 5432 -U username -F c -b -v -f dumpfilename.dump databasename
Франциско Луз
источник
Хорошо, но, к сожалению, у меня ничего не получается, я получаю «запрос не выполнен: ОШИБКА: в отношении direction_lookup отказано в разрешении»
Джеймс Т Снелл
@ Док вы пытались дать необходимые разрешения пользователю pg?
Франциско Луз
33

Этот лайнер помогает мне при создании дампа одной базы данных.

PGPASSWORD="yourpassword" pg_dump -U postgres -h localhost mydb > mydb.pgsql
Aarvy
источник
1
очень помогло ... thnxxx
ronit
19

@Josue Александр Ибарра ответ работает на centos 7 и версии 9.5, если --dbname не передано.

pg_dump postgresql://username:password@127.0.0.1:5432/mydatabase 
Jauyzed
источник
1
Вы правы, вот как это должно выглядеть, я думаю, что несколько лет назад было неправильно моя конфигурация оболочки. Вот почему это было важно для меня, чтобы использовать--dbname
Хосе Александр Ибарра
7

Обратите внимание, что в Windows pgpass.confфайл должен находиться в следующей папке:

%APPDATA%\postgresql\pgpass.conf

если postgresqlвнутри %APPDATA%папки нет папки, создайте ее.

pgpass.confсодержимое файла что - то вроде:

localhost:5432:dbname:dbusername:dbpassword

ура

Фернандо Менезес Гомес
источник
4

Поправьте меня, если я ошибаюсь, но если системный пользователь совпадает с пользователем базы данных, PostgreSQL не будет запрашивать пароль - он использует систему для аутентификации. Это может быть вопросом конфигурации.

Таким образом, когда я хотел владельца базы данных postgresдля резервного копирования своих баз данных каждую ночь, я мог бы создать кронтаб для него: crontab -e -u postgres. Конечно, postgresнужно разрешить выполнять задания cron; таким образом, он должен быть указан /etc/cron.allowили /etc/cron.denyдолжен быть пустым.

Тобиас
источник
Вы вроде как здесь. Конфигурация Postgres по умолчанию использует аутентификацию TRUST для учетных записей локальной системы. Однако большинство производственных установок избавляются от этого блока сразу после установки СУБД.
Яцек Прусия
4

Сделайте резервную копию через ssh с паролем, используя временные учетные данные .pgpass и отправьте на S3:

#!/usr/bin/env bash
cd "$(dirname "$0")"

DB_HOST="*******.*********.us-west-2.rds.amazonaws.com"
DB_USER="*******"
SSH_HOST="my_user@host.my_domain.com"
BUCKET_PATH="bucket_name/backup"

if [ $# -ne 2 ]; then
    echo "Error: 2 arguments required"
    echo "Usage:"
    echo "  my-backup-script.sh <DB-name> <password>"
    echo "  <DB-name> = The name of the DB to backup"
    echo "  <password> = The DB password, which is also used for GPG encryption of the backup file"
    echo "Example:"
    echo "  my-backup-script.sh my_db my_password"
    exit 1
fi

DATABASE=$1
PASSWORD=$2

echo "set remote PG password .."
echo "$DB_HOST:5432:$DATABASE:$DB_USER:$PASSWORD" | ssh "$SSH_HOST" "cat > ~/.pgpass; chmod 0600 ~/.pgpass"
echo "backup over SSH and gzip the backup .."
ssh "$SSH_HOST" "pg_dump -U $DB_USER -h $DB_HOST -C --column-inserts $DATABASE" | gzip > ./tmp.gz
echo "unset remote PG password .."
echo "*********" | ssh "$SSH_HOST" "cat > ~/.pgpass"
echo "encrypt the backup .."
gpg --batch --passphrase "$PASSWORD" --cipher-algo AES256 --compression-algo BZIP2 -co "$DATABASE.sql.gz.gpg" ./tmp.gz

# Backing up to AWS obviously requires having your credentials to be set locally
# EC2 instances can use instance permissions to push files to S3
DATETIME=`date "+%Y%m%d-%H%M%S"`
aws s3 cp ./"$DATABASE.sql.gz.gpg" s3://"$BUCKET_PATH"/"$DATABASE"/db/"$DATETIME".sql.gz.gpg
# s3 is cheap, so don't worry about a little temporary duplication here
# "latest" is always good to have because it makes it easier for dev-ops to use
aws s3 cp ./"$DATABASE.sql.gz.gpg" s3://"$BUCKET_PATH"/"$DATABASE"/db/latest.sql.gz.gpg

echo "local clean-up .."
rm ./tmp.gz
rm "$DATABASE.sql.gz.gpg"

echo "-----------------------"
echo "To decrypt and extract:"
echo "-----------------------"
echo "gpg -d ./$DATABASE.sql.gz.gpg | gunzip > tmp.sql"
echo

Просто замените первые пару строк конфигурации на то, что вам нужно - очевидно. Для тех, кто не заинтересован в резервной части S3, возьмите это - очевидно.

Этот сценарий .pgpassвпоследствии удаляет учетные данные, поскольку в некоторых средах пользователь SSH по умолчанию может выполнять sudo без пароля, например, экземпляр EC2 с ubuntuпользователем, поэтому использование .pgpassдругой учетной записи хоста для защиты этих учетных данных может быть бессмысленным.

MikeM
источник
Пароль будет зарегистрирован в терминале historyтаким образом, нет?
mpen
1
@mpen Локально, да. Удаленно нет. В моем случае это нормально иметь в моей локальной истории, потому что это безопасная виртуальная машина, которая не разрешает удаленный доступ. Если в вашем случае это не хорошо, просто сделайте history -c. При использовании с Jenkins используйте эту Inject passwords to the build as environment variablesопцию, чтобы пароль был замаскирован
MikeM
4

Как подробно описано в этом блоге , существует два способа неинтерактивно предоставлять пароль для утилит PostgreSQL, таких как команда «pg_dump»: с помощью файла «.pgpass» или с помощью переменной среды «PGPASSWORD» .

manfall19
источник
-1

Другой (возможно, небезопасный) способ передачи пароля - это использование перенаправления ввода, т.е.

pg_dump [params] < [path to file containing password]

szymond
источник
Что касается безопасности - этот файл должен быть доступен для чтения только предполагаемым пользователям; однако любой пользователь с правами root сможет изменить настройки безопасности и, следовательно, прочитать незашифрованный пароль. Так что да, это небезопасно ...
Тобиас
3
@Tobias есть ли альтернатива? Казалось бы, любой пользователь с правами root всегда может видеть пароль независимо от того, какой метод, кроме как ввод пароля в интерактивном режиме (и вопрос о cron). postgresql.org/docs/9.3/static/auth-methods.html#GSSAPI-AUTH упоминает GSSAPI, поддерживающий единый вход, но не упоминает, работает ли он не в интерактивном режиме.
Росс Брэдбери
4
Любой пользователь с правами root может также прочитать .pgpass, который является рекомендуемым способом. Поэтому я бы не стал рассматривать корневой доступ как угрозу безопасности.
максимум
-1

Вы можете передать пароль в pg_dump напрямую, используя следующее:

pg_dump "host=localhost port=5432 dbname=mydb user=myuser password=mypass" > mydb_export.sql
Ларри Спенс
источник
Добро пожаловать в стек переполнения! Хотя ваш ответ может сработать, он имеет серьезные последствия для безопасности. Аргументы команды видны в ps (1) , поэтому, если процесс отслеживает ps (1), пароль подвергается риску.
Джонатан Роза
-4

самый простой способ, на мой взгляд, это: вы редактируете свой основной файл конфигурации postgres: pg_hba.conf, там вы должны добавить следующую строку:

host <you_db_name> <you_db_owner> 127.0.0.1/32 trust

и после этого вам нужно запустить cron так:

pg_dump -h 127.0.0.1 -U <you_db_user> <you_db_name> | gzip > /backup/db/$(date +%Y-%m-%d).psql.gz

и это работало без пароля

Dofri
источник
И вы только что разрушили систему безопасности. ОК для коробки разработчика, но больше ничего.
Теодор Р. Смит