Como passar a senha para pg_dump?

294

Estou tentando criar um cronjob para fazer backup do meu banco de dados todas as noites antes que algo catastrófico aconteça. Parece que este comando deve atender às minhas necessidades:

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

Exceto depois de executar isso, ele espera que eu digite uma senha. Eu não posso fazer isso se o executar no cron. Como posso passar um automaticamente?

mpen
fonte
possivelmente útil post que escrevi sobre como automatizar pg_restore! medium.com/@trinity/…
kittyminky
responda usando uma cadeia de conexão aqui: stackoverflow.com/a/29101292/1579667
Benj

Respostas:

304

Crie um .pgpassarquivo no diretório inicial da conta que pg_dumpserá executada como. Veja a documentação do Postgresql libpq-pgpass para detalhes do formato (incluindo o último parágrafo onde explica que será ignorado se você não definir o modo 0600).

araqnid
fonte
99
Criar ~ / .pgpass com localhost: 5432: mydbname: postgres: mypass Então chmod 600 ~ / .pgpass
Mircea Stanciu
6
Possivelmente útil: No Ubuntu, "sudo su postgres" para alternar para o usuário "postgres", crie o arquivo .pgpass e execute o dump.
Fivedogit 21/05
1
Eu segui sua resposta, mas ainda não consegui criar com êxito o meu arquivo de backup. Por favor, veja o meu link: unix.stackexchange.com/questions/257898/… . Obrigado.
Alyssaeliyah
Funciona em 9.6.2: o)
Andrew
2
Nota sobre sudo su postgres: esse usuário Unix não existe necessariamente. Não precisa. Mas o usuário do banco de dados deve.
Fabien Haddadi
216

Ou você pode configurar o crontab para executar um script. Dentro desse script, você pode definir uma variável de ambiente como esta: export PGPASSWORD="$put_here_the_password"

Dessa forma, se você tiver vários comandos que exigiriam senha, poderá colocá-los todos no script. Se a senha mudar, você precisará alterá-la apenas em um lugar (o script).

E eu concordo com Joshua, usando pg_dump -Fcgera o formato de exportação mais flexível e já está compactado. Para mais informações, consulte: documentação pg_dump

Por exemplo

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

# restore the database
pg_restore -d newdb db.dump
Máx.
fonte
3
isso não é o ideal. jogá-lo .pgpasstambém manterá tudo em um só lugar, sem adicionar uma camada extra de indireção. além disso, se tudo o que eu queria fazer com a exportação de uma variável, eu faria isso no meu .bashrcarquivo, ou seja o que for.
MPEN
9
Eu posso ver por que o .pgpassarquivo seria uma solução melhor. Eu estava apenas dando uma alternativa, não tenho certeza se ele merece uma downvote embora :)
Max
13
Eu não voto negativo. Essa era outra pessoa; Também não achei que isso justificasse um voto negativo. Tenha um +1 para compensar isso.
MPEN
7
Tantos odiadores. Agradeço esta resposta e a estou adotando para meu próprio aplicativo.
James T Snell
8
Definir a variável de ambiente PGPASSWORD não é uma prática recomendada pela documentação ( postgresql.org/docs/current/static/libpq-envars.html ): o uso dessa variável de ambiente não é recomendado por razões de segurança, pois alguns sistemas operacionais permitem usuários root para ver variáveis ​​de ambiente do processo via ps; em vez disso, considere usar o arquivo ~ / .pgpass
bouchon
175

Se você quiser fazer isso em um comando:

PGPASSWORD="mypass" pg_dump mydb > mydb.dump
gitaarik
fonte
27
Definir a variável de ambiente PGPASSWORD não é uma prática recomendada pela documentação ( postgresql.org/docs/current/static/libpq-envars.html ): o uso dessa variável de ambiente não é recomendado por razões de segurança, pois alguns sistemas operacionais permitem usuários root para ver variáveis ​​de ambiente do processo via ps; em vez disso, considere usar o arquivo ~ / .pgpass
bouchon
18
Ainda é um comentário útil. Existem muitos casos de implantação em que isso ainda é útil.
Iain Duncan
1
Sempre recebi o erro 'Falha na autenticação de pares para o usuário "nome de usuário"'. A solução foi: PGPASSWORD = "mypass" pg_dump -U nome de usuário -h localhost> mydb.dump
Martin Pabst
4
Minha opinião é que é muito melhor configurar uma variável de ambiente (onde você tem controle, onde e como a senha será armazenada) como em um local conhecido e não criptografado. Esta parte do documento do postgresql está com defeito e essa resposta é boa.
peterh - Restabelece Monica
1
Minha senha tinha um '@'. Isso funcionou. Eu não conseguia descobrir como fazê-lo funcionar com a postgres://sintaxe. Não tentei o .pgpassporque meu usuário do postgress não tem diretório inicial.
precisa saber é
136

Para um one-liner, como migrar um banco de dados, você pode usar --dbnameseguido por uma cadeia de conexão (incluindo a senha), conforme indicado no manual pg_dump

Em essência.

pg_dump --dbname=postgresql://username:[email protected]:5432/mydatabase

Nota: Certifique-se de usar a opção em --dbnamevez da mais curta -de use um prefixo de URI válido postgresql://ou postgres://.

O formulário URI geral é:

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

A melhor prática no seu caso (tarefa repetitiva no cron) não deve ser feita devido a problemas de segurança. Se não fosse o .pgpassarquivo, eu salvaria a cadeia de conexão como uma variável de ambiente.

export MYDB=postgresql://username:[email protected]:5432/mydatabase

então tenha no seu crontab

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

Josue Alexander Ibarra
fonte
Versão 9.1 do Postgre emite uma opção desconhecida para dbname
akohout
Isso foi testado nas versões 9.4 e 9.3 no arch e RHEL, respectivamente. você pode postar sua string de conexão? anonimizado, é claro.
Josue Alexander Ibarra
Obrigado, @ JosueIbarra. Testado com sucesso no PostgreSQL 9.3, Ubuntu 14.04.
Cao Minh Tu
1
@EntryLevelR, você precisa canalizar a saída para um arquivo para salvá-la. veja esta questão relevante askubuntu.com/questions/420981/...
Josue Alexander Ibarra
4
essa deve ser a resposta aceita. Um forro, claro.
swdev
48
$ PGPASSWORD="mypass" pg_dump -i -h localhost -p 5432 -U username -F c -b -v -f dumpfilename.dump databasename
Francisco Luz
fonte
Bom, mas infelizmente não funciona para mim, eu recebo "consulta falhou: ERRO: permissão negada para relação direction_lookup"
James T Snell
@Doc você tentou dar as permissões necessárias para o usuário pg?
Francisco Luz
33

Esse liner me ajuda a criar o despejo de um único banco de dados.

PGPASSWORD="yourpassword" pg_dump -U postgres -h localhost mydb > mydb.pgsql
Aarvy
fonte
1
ajudou muito ... thnxxx
ronit 11/11/19
19

A resposta de Joseph Alexander Ibarra funciona no centos 7 e na versão 9.5 se --dbname não for passado.

pg_dump postgresql://username:[email protected]:5432/mydatabase 
Jauyzed
fonte
1
Você está certo, é assim que deve parecer, acho que o que estava errado alguns anos atrás era a minha configuração de shell. É por isso era essencial para mim usar--dbname
Josue Alexander Ibarra
7

Observe que, no Windows, o pgpass.confarquivo deve estar na seguinte pasta:

%APPDATA%\postgresql\pgpass.conf

se não houver postgresqlpasta dentro da %APPDATA%pasta, crie-a.

o pgpass.confconteúdo do arquivo é algo como:

localhost:5432:dbname:dbusername:dbpassword

Felicidades

Fernando Meneses Gomes
fonte
4

Corrija-me se eu estiver errado, mas se o usuário do sistema for o mesmo que o usuário do banco de dados, o PostgreSQL não solicitará a senha - ele depende do sistema para autenticação. Isso pode ser uma questão de configuração.

Assim, quando eu queria o proprietário do banco de dados postgrespara backup de seus bancos de dados todas as noites, eu poderia criar um crontab para ele: crontab -e -u postgres. Obviamente, postgresseria necessário executar tarefas cron; portanto, ele deve estar listado /etc/cron.allowou /etc/cron.denyestar vazio.

Tobias
fonte
Você está meio que aqui. A configuração padrão do Postgres usa autenticação TRUST para contas do sistema local. No entanto, a maioria das configurações de produção se livra desse bloco logo após a instalação do RDBMS.
Jacek Prucia
4

Faça backup do ssh com senha usando credenciais temporárias .pgpass e envie para o S3:

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

DB_HOST="*******.*********.us-west-2.rds.amazonaws.com"
DB_USER="*******"
SSH_HOST="[email protected]_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

Apenas substitua o primeiro par de linhas de configuração pelo que você precisar - obviamente. Para aqueles que não estão interessados ​​na parte de backup do S3, retire-o - obviamente.

Esse script exclui as credenciais .pgpassposteriormente porque, em alguns ambientes, o usuário SSH padrão pode executar o sudo sem uma senha, por exemplo, uma instância do EC2 com o ubuntuusuário, portanto, o uso .pgpasscom uma conta de host diferente para proteger essas credenciais pode ser inútil.

MikeM
fonte
A senha será registrada no terminal historydessa maneira, não?
MPEN
1
@mpen Localmente, sim. Remotamente, não. No meu caso, não há problema em ter no meu histórico local, porque é uma VM segura que não permite acesso remoto. Se no seu caso isso não estiver bom, basta fazê-lo history -c. Ao utilizar com Jenkins, use a Inject passwords to the build as environment variablesopção para que a senha é mascarado
MikeM
4

Conforme detalhado nesta publicação , existem duas maneiras de fornecer uma senha de maneira não interativa aos utilitários do PostgreSQL, como o comando "pg_dump": usando o arquivo ".pgpass" ou a variável de ambiente "PGPASSWORD" .

manfall19
fonte
-1

Outra maneira (provavelmente não segura) de passar a senha é usar o redirecionamento de entrada, ou seja, chamar

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

Szymond
fonte
Em relação à segurança - esse arquivo precisa ser legível apenas pelo (s) usuário (s) pretendido (s); no entanto, qualquer pessoa com direitos de root poderá alterar as configurações de segurança e, assim, ler a senha não criptografada. Então, sim, este é inseguro ...
Tobias
3
@ Tobias existe alguma alternativa? Parece que qualquer pessoa com direitos de root sempre pode ver a senha, independentemente da técnica, além de inserir a senha interativamente (e a pergunta é sobre o cron). postgresql.org/docs/9.3/static/auth-methods.html#GSSAPI-AUTH menciona o GSSAPI suportando logon único, mas nenhuma menção se isso funcionar de maneira não interativa.
Ross Bradbury
4
Qualquer pessoa com direitos de root também pode ler o .pgpass, que é o caminho recomendado. Portanto, eu não consideraria o acesso root um risco à segurança.
máx
-1

Você pode passar uma senha diretamente para o pg_dump usando o seguinte:

pg_dump "host=localhost port=5432 dbname=mydb user=myuser password=mypass" > mydb_export.sql
Larry Spence
fonte
Bem-vindo ao Stack Overflow! Embora sua resposta possa funcionar, ela tem sérias implicações de segurança. Os argumentos de um comando são visíveis no ps (1) , portanto, se um processo monitora o ps (1), a senha fica comprometida.
Jonathan Rosa
-4

da maneira mais fácil na minha opinião, isso: você edita seu arquivo de configuração principal do postgres: pg_hba.conf, você deve adicionar a seguinte linha:

host <you_db_name> <you_db_owner> 127.0.0.1/32 trust

e depois disso, você precisa iniciar o cron assim:

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

e funcionou sem senha

Dofri
fonte
E você acabou de destruir a segurança do sistema. OK para uma caixa de desenvolvimento, mas nada mais.
Theodore R. Smith