จะส่งรหัสผ่านไปยัง 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

คำตอบ:


304

สร้าง.pgpassไฟล์ในโฮมไดเรกทอรีของบัญชีที่pg_dumpจะใช้งาน ดู Postgresql เอกสารประกอบlibpq-pgpassสำหรับรายละเอียดของรูปแบบ (รวมถึงย่อหน้าสุดท้ายที่อธิบายถึงมันจะถูกละเว้นหากคุณไม่ได้ตั้งโหมดเป็น0600)


99
สร้าง ~ / .pgpass ด้วย localhost: 5432: mydbname: postgres: mypass จากนั้น chmod 600 ~ / .pgpass
Mircea Stanciu

6
อาจมีประโยชน์: บน Ubuntu, "sudo su postgres" เพื่อสลับไปยังผู้ใช้ "postgres" จากนั้นสร้างไฟล์ .pgpass และดำเนินการถ่ายโอนข้อมูล
fivedogit

1
ฉันทำตามคำตอบของคุณแล้ว แต่ก็ยังไม่สามารถสร้างไฟล์สำรองของฉันได้สำเร็จ โปรดดูการเชื่อมโยงของฉัน: unix.stackexchange.com/questions/257898/... ขอบคุณ.
alyssaeliyah

ใช้งานได้กับ 9.6.2: o)
แอนดรูว์

2
หมายเหตุเกี่ยวกับsudo su postgres: ผู้ใช้ Unix นั้นไม่จำเป็นต้องมีอยู่จริง มันไม่จำเป็นต้อง แต่ผู้ใช้ DB ควร
Fabien Haddadi

217

หรือคุณสามารถตั้งค่า 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ไฟล์ถึงเป็นทางออกที่ดีกว่า ผมก็แค่ให้ทางเลือกที่ไม่แน่ใจว่ามันสมควร downvote แม้ว่า :)
แม็กซ์

13
ฉันไม่ได้ลงคะแนน นั่นคือคนอื่น ฉันไม่คิดว่ามันจะรับประกันการโหวตอย่างใดอย่างหนึ่ง มี +1 เพื่อชดเชย
mpen

7
เกลียดชังมากมาย ฉันขอขอบคุณคำตอบนี้และฉันก็ยอมรับมันสำหรับแอปพลิเคชันของฉันเอง
James T Snell

8
การตั้งค่าตัวแปรสภาพแวดล้อม PGPASSWORD ไม่ใช่วิธีปฏิบัติที่แนะนำโดยเอกสารประกอบ ( postgresql.org/docs/current/static/libpq-envars.html ): ไม่แนะนำให้ใช้ตัวแปรสภาพแวดล้อมนี้เนื่องจากเหตุผลด้านความปลอดภัยเนื่องจากระบบปฏิบัติการบางระบบอนุญาตให้ใช้ ผู้ใช้รูทเพื่อดูตัวแปรสภาวะแวดล้อมกระบวนการผ่าน ps; ให้พิจารณาใช้ไฟล์ ~ / .pgpass แทน
bouchon

175

หากคุณต้องการที่จะทำมันในหนึ่งคำสั่ง:

PGPASSWORD="mypass" pg_dump mydb > mydb.dump

27
การตั้งค่าตัวแปรสภาพแวดล้อม PGPASSWORD ไม่ใช่วิธีปฏิบัติที่แนะนำโดยเอกสารประกอบ ( postgresql.org/docs/current/static/libpq-envars.html ): ไม่แนะนำให้ใช้ตัวแปรสภาพแวดล้อมนี้เนื่องจากเหตุผลด้านความปลอดภัยเนื่องจากระบบปฏิบัติการบางระบบอนุญาตให้ใช้ ผู้ใช้รูทเพื่อดูตัวแปรสภาวะแวดล้อมกระบวนการผ่าน ps; ให้พิจารณาใช้ไฟล์ ~ / .pgpass แทน
bouchon

18
มันยังเป็นความคิดเห็นที่มีประโยชน์ มีกรณีการปรับใช้จำนวนมากซึ่งสิ่งนี้ยังมีประโยชน์อยู่
เลน Duncan

1
ฉันได้รับข้อผิดพลาดเสมอ 'การตรวจสอบสิทธิ์เพื่อนไม่สำเร็จสำหรับผู้ใช้ "ชื่อผู้ใช้"' วิธีแก้ไขคือ: PGPASSWORD = "mypass" pg_dump ชื่อผู้ใช้ -U localhost> mydb.dump
Martin Pabst

4
ความคิดเห็นของฉันคือมันจะดีกว่าการตั้งค่าตัวแปรสภาพแวดล้อม (ที่คุณมีการควบคุมที่ไหนและวิธีการจัดเก็บรหัสผ่าน) ในสถานที่ที่รู้จักและไม่ได้เข้ารหัส ส่วนนี้ของ postgresql doc เป็นความผิดพลาดและคำตอบนี้เป็นคำตอบที่ดี
peterh - Reinstate Monica

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


Postgre เวอร์ชัน 9.1 แสดงตัวเลือกที่ไม่รู้จักสำหรับ dbname
akohout

สิ่งนี้ถูกทดสอบด้วยเวอร์ชัน 9.4 และ 9.3 บน arch และ RHEL ตามลำดับ คุณสามารถโพสต์สตริงการเชื่อมต่อของคุณ? ไม่ระบุชื่อแน่นอน
Josue Alexander Ibarra

ขอบคุณ @JosueIbarra ผ่านการทดสอบเรียบร้อยแล้วใน PostgreSQL 9.3, Ubuntu 14.04
Cao Minh Tu

1
@EntryLevelR คุณต้องไพพ์เอาต์พุตไปยังไฟล์เพื่อบันทึก ดูคำถามที่เกี่ยวข้องนี้Askubuntu.com/questions/420981/ …
Josue Alexander Ibarra

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

@Doc คุณได้ลองให้สิทธิ์ที่จำเป็นแก่ผู้ใช้ pg แล้วหรือยัง?
Francisco Luz

33

ซับเดียวนี้ช่วยฉันในขณะที่สร้างดัมพ์ของฐานข้อมูลเดียว

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

1
ช่วยได้มาก ... thnxxx
ronit

19

@Josue Alexander Ibarra คำตอบใช้ได้กับ centos 7 และรุ่น 9.5 หาก --dbname ไม่ผ่าน

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

1
คุณคิดถูกแล้วนี่คือวิธีที่ฉันควรมองฉันคิดว่าสิ่งที่ผิดพลาดไม่กี่ปีหลังคือการกำหนดค่าเปลือก นั่นเป็นเหตุผลที่ฉันจำเป็นต้องใช้--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 เริ่มต้นใช้การตรวจสอบความน่าเชื่อถือสำหรับบัญชีระบบภายใน อย่างไรก็ตามการตั้งค่าการผลิตส่วนใหญ่กำจัดบล็อกนี้ทันทีหลังจากติดตั้ง RDBMS
Jacek Prucia

4

สำรองข้อมูลผ่าน ssh ด้วยรหัสผ่านโดยใช้ข้อมูลประจำตัว. mpg ชั่วคราวแล้วกดไปที่ 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

เพียงแทนที่สองบรรทัดแรกของ config ด้วยสิ่งที่คุณต้องการ - อย่างชัดเจน สำหรับผู้ที่ไม่สนใจในส่วนสำรอง S3 ให้นำออก - อย่างชัดเจน

สคริปต์นี้จะลบข้อมูลรับรองใน.pgpassภายหลังเนื่องจากในบางสภาพแวดล้อมผู้ใช้ SSH เริ่มต้นสามารถ sudo โดยไม่ต้องใช้รหัสผ่านเช่นอินสแตนซ์ EC2 กับubuntuผู้ใช้ดังนั้นการใช้.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]


เกี่ยวกับความปลอดภัย - ไฟล์นี้จะต้องสามารถอ่านได้โดยผู้ใช้ที่ตั้งใจเท่านั้น อย่างไรก็ตามทุกคนที่มีสิทธิ์รูทจะสามารถเปลี่ยนการตั้งค่าความปลอดภัยได้และเพื่ออ่านรหัสผ่านที่ไม่ได้เข้ารหัส ใช่แล้วนี่มันไม่ปลอดภัย ...
Tobias

3
@Tobias มีทางเลือกอื่นอีกไหม? ดูเหมือนว่าทุกคนที่มีสิทธิ์รูทสามารถเห็นรหัสผ่านได้เสมอไม่ว่าจะใช้เทคนิคใดนอกจากการป้อนรหัสผ่านแบบโต้ตอบ (และคำถามนี้เกี่ยวกับ cron) postgresql.org/docs/9.3/static/auth-methods.html#GSSAPI-AUTHกล่าวถึง GSSAPI ที่สนับสนุนการลงชื่อเข้าใช้เพียงครั้งเดียว
Ross Bradbury

4
ทุกคนที่มีสิทธิ์ใช้งานรูทสามารถอ่าน .pg ผ่านวิธีที่แนะนำได้ ดังนั้นฉันจะไม่พิจารณาการเข้าถึงความเสี่ยงด้านความปลอดภัย
สูงสุด

-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

วิธีที่ง่ายที่สุดในความคิดของฉันนี้: คุณแก้ไขไฟล์ config 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

และมันทำงานได้โดยไม่ต้องใช้รหัสผ่าน


และคุณเพิ่งทำลายความปลอดภัยของระบบ ตกลงสำหรับกล่อง dev แต่ไม่มีอะไรอื่น
Theodore R. Smith
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.