如何将密码传递给pg_dump?


294

我正在尝试创建一个cronjob来每晚在灾难性事件发生之前备份我的数据库。看起来此命令应该可以满足我的需求:

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

除了运行之后,它希望我输入密码。如果我从cron运行它,我将无法做到这一点。如何自动传递一个?


我在自动化pg_restore上写的可能有用的帖子!medium.com/@trinity/…–
kittyminky

在这里使用连接字符串回答:stackoverflow.com/a/29101292/1579667
Benj

Answers:


304

.pgpasspg_dump将运行身份的帐户的主目录中创建一个文件。有关格式的详细信息,请参见Postgresql文档libpq-pgpass(包括最后一段,其中说明了该格式,如果未将mode设置为,则将被忽略0600)。


98
使用localhost:5432:mydbname:postgres:mypass创建〜/ .pgpass,然后使用chmod 600〜/ .pgpass
Mircea Stanciu

6
可能有帮助:在Ubuntu上,将“ sudo su postgres”切换到“ postgres”用户,然后创建.pgpass文件并执行转储。
Fivedogit

1
我遵循了您的回答,但仍然无法成功创建备份文件。请参阅我的链接:unix.stackexchange.com/questions/257898/…。谢谢。
alyssaeliyah

在9.6.2上工作:o)
Andrew

2
关于的注意事项sudo su postgres:Unix用户不一定存在。不需要。但是数据库用户应该。
法比恩·哈达迪

216

或者,您可以设置crontab来运行脚​​本。在该脚本中,您可以设置如下环境变量: export PGPASSWORD="$put_here_the_password"

这样,如果您有多个需要密码的命令,则可以将它们全部放入脚本中。如果更改了密码,则只需在一个位置(脚本)进行更改。

我同意Joshua的观点,他使用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文件将是更好的解决方案。我只是提供一个替代方案,虽然不确定是否值得投票:)
Max

13
我没有投票。那是别人 我也不认为这值得一票。有+1可以弥补。
mpen

7
这么多仇恨者。我很欣赏这个答案,并正在为我自己的应用程序采用它。
James T Snell 2015年

8
文档postgresql.org/docs/current/static/libpq-envars.html不建议您设置PGPASSWORD环境变量出于安全原因,不建议使用此环境变量,因为某些操作系统允许使用非超级用户可以通过ps查看进程环境变量;而是考虑使用〜/ .pgpass文件
bouchon

175

如果要在一个命令中执行此操作:

PGPASSWORD="mypass" pg_dump mydb > mydb.dump

27
文档(postgresql.org/docs/current/static/libpq-envars.html不建议您设置PGPASSWORD环境变量出于安全原因,不建议使用此环境变量,因为某些操作系统允许使用非超级用户可以通过ps查看进程环境变量;而是考虑使用〜/ .pgpass文件
bouchon

18
这仍然是一个有用的评论。在许多部署案例中,这仍然有帮助。
伊恩·邓肯

1
我总是收到错误“用户“用户名”的对等身份验证失败”。解决方案是:PGPASSWORD =“ mypass” pg_dump -U用户名-h localhost> mydb.dump
Martin Pabst

4
我的观点是,最好在一个未加密的已知位置设置环境变量(您可以控制,在何处以及如何存储密码)。postgresql doc的这一部分有问题,这个答案是一个很好的答案。
彼得-恢复莫妮卡

1
我的密码中有一个“ @”。这工作了。我无法弄清楚如何使其与postgres://语法一起使用。没有尝试,.pgpass因为我的postgress用户没有主目录。
jmathew

136

对于单行代码,就像迁移数据库一样,您可以使用pg_dump手册--dbname中所述的后跟连接字符串(包括密码)

在本质上。

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


Postgre 9.1版输出的dbname未知选项
akohout 2015年

分别在arch和RHEL上使用版本9.4和9.3进行了测试。您可以发布连接字符串吗?当然是匿名的。
Josue Alexander Ibarra 2015年

谢谢@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的权限被拒绝”
James T Snell 2015年

@Doc您是否尝试将必要的权限授予pg用户?
Francisco Luz 2015年

33

在创建单个数据库的转储时,这一行可以帮助我。

PGPASSWORD="yourpassword" pg_dump -U postgres -h localhost mydb > mydb.pgsql

1
帮助了很多... thnxxx
ronit

19

如果未传递--dbname,则@Josue Alexander Ibarra答案适用于centos 7和9.5版。

pg_dump postgresql://username:password@127.0.0.1:5432/mydatabase 

1
没错,这就是它的外观,我认为几年前出了问题的是我的shell配置。这就是为什么我必须使用它的原因--dbname
Josue Alexander Ibarra

7

请注意,在Windows中,该pgpass.conf文件必须位于以下文件夹中:

%APPDATA%\postgresql\pgpass.conf

如果postgresql文件夹内没有文件%APPDATA%夹,请创建它。

pgpass.conf文件内容是这样的:

localhost:5432:dbname:dbusername:dbpassword

干杯


4

如果我错了,请纠正我,但是如果系统用户与数据库用户相同,则PostgreSQL不会要求输入密码-它依赖于系统进行身份验证。这可能是配置问题。

因此,当我希望数据库所有者postgres每晚都备份他的数据库时,可以为其创建一个crontab crontab -e -u postgres。当然,postgres将需要允许执行cron作业;因此,它必须在中列出/etc/cron.allow,或者/etc/cron.deny必须为空。


您就在这里。默认的Postgres配置对本地系统帐户使用TRUST身份验证。但是,大多数生产设置在安装RDBMS之后就立即摆脱了这一障碍。
Jacek Prucia,2014年

4

使用临时.pgpass凭据通过ssh进行密码备份,然后推送到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,例如,与该ubuntu用户一起使用的EC2实例,因此使用.pgpass其他主机帐户来保护这些凭据可能没有意义。


密码将以history这种方式登录到终端,不是吗?
mpen

1
@mpen在本地,是的。从远处看,没有。就我而言,可以在我的本地历史记录中查看是因为它是一个安全的VM,不允许远程访问。如果您的情况不正确,请执行history -c。当与Jenkins一起使用时,请使用该Inject passwords to the build as environment variables选项以使密码被屏蔽
MikeM

4

本博文中所述,有两种方法可以非交互方式向PostgreSQL实用程序提供密码,例如“ pg_dump”命令:使用“ .pgpass”文件或使用“ PGPASSWORD”环境变量。


-1

传递密码的另一种(可能不安全)方法是使用输入重定向,即调用

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


关于安全性-该文件只需要预期的用户读取;但是,具有root权限的任何人都可以更改安全设置,从而读取未加密的密码。所以是的,这是不安全的……
Tobias

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

欢迎使用Stack Overflow!尽管您的答案可能有效,但它对安全性有严重影响。命令的参数在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

它没有密码就可以工作


您刚刚破坏了系统安全性。确定开发人员框,但没有其他。
西奥多·R·史密斯,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.