Jak przekazać hasło do pg_dump?

294

Próbuję utworzyć cronjob do tworzenia kopii zapasowych mojej bazy danych każdej nocy, zanim wydarzy się coś katastrofalnego. Wygląda na to, że to polecenie powinno spełniać moje potrzeby:

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

Z wyjątkiem tego, że po uruchomieniu tego wymaga ode mnie wpisania hasła. Nie mogę tego zrobić, jeśli uruchomię go z crona. Jak mogę przekazać je automatycznie?

mpen
źródło
prawdopodobnie pomocny post, który napisałem o automatyzacji pg_restore! medium.com/@trinity/…
kittyminky
odpowiedz za pomocą ciągu połączenia tutaj: stackoverflow.com/a/29101292/1579667
Benj

Odpowiedzi:

304

Utwórz .pgpassplik w katalogu głównym konta, które pg_dumpbędzie działać jako. Zobacz dokumentację Postgresql libpq-pgpass, aby uzyskać szczegółowe informacje na temat formatu (w tym ostatni akapit, w którym wyjaśniono, że zostanie zignorowany, jeśli nie ustawisz trybu na 0600).

araqnid
źródło
99
Utwórz ~ / .pgpass z localhost: 5432: moja_nazwa: postgres: mypass Następnie chmod 600 ~ / .pgpass
Mircea Stanciu
6
Prawdopodobnie pomocne: w systemie Ubuntu „sudo su postgres”, aby przełączyć się na użytkownika „postgres”, a następnie utworzyć plik .pgpass i wykonać zrzut.
fivedogit
1
Postąpiłem zgodnie z odpowiedzią, ale nadal nie mogę pomyślnie utworzyć pliku kopii zapasowej. Proszę zobaczyć mój link: unix.stackexchange.com/questions/257898/... . Dziękuję Ci.
alyssaeliyah
Działa z 9.6.2: o)
Andrew
2
Uwaga na temat sudo su postgres: ten użytkownik systemu Unix niekoniecznie istnieje. Nie musi. Ale użytkownik DB powinien.
Fabien Haddadi,
216

Lub możesz skonfigurować crontab do uruchamiania skryptu. Wewnątrz tego skryptu możesz ustawić zmienną środowiskową taką jak ta: export PGPASSWORD="$put_here_the_password"

W ten sposób, jeśli masz wiele poleceń wymagających hasła, możesz umieścić je wszystkie w skrypcie. Jeśli hasło się zmieni, musisz je zmienić tylko w jednym miejscu (skrypt).

I zgadzam się z Joshua, użycie pg_dump -Fcgeneruje najbardziej elastyczny format eksportu i jest już skompresowany. Aby uzyskać więcej informacji, zobacz: dokumentacja pg_dump

Na przykład

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

# restore the database
pg_restore -d newdb db.dump
Max
źródło
3
to nie jest idealne. wrzucenie go .pgpasszatrzyma wszystko w jednym miejscu, bez dodawania dodatkowej warstwy pośredniej. ponadto, jeśli wszystko, co chciałem zrobić z eksportem zmiennej, zrobiłbym to w moim .bashrcpliku lub czymkolwiek innym .
mpen 15.11.11
9
Rozumiem, dlaczego .pgpassplik byłby lepszym rozwiązaniem. Dałem tylko alternatywę, nie jestem pewien, czy zasługuje ona na głosowanie :)
Max
13
Nie przegłosowałem. To był ktoś inny; Nie sądziłem też, że uzasadnia to głosowanie negatywne. Masz +1, aby to nadrobić.
mpen 15.11. O
7
Tyle hejterów. Doceniam tę odpowiedź i przyjmuję ją do własnego wniosku.
James T Snell
8
Ustawienie zmiennej środowiskowej PGPASSWORD nie jest zalecaną praktyką w dokumentacji ( postgresql.org/docs/current/static/libpq-envars.html ): Używanie tej zmiennej środowiskowej nie jest zalecane ze względów bezpieczeństwa, ponieważ niektóre systemy operacyjne zezwalają na root użytkowników, aby zobaczyć zmienne środowiskowe procesu za pomocą ps; zamiast tego rozważ użycie pliku ~ / .pgpass
bouchon
175

Jeśli chcesz to zrobić za pomocą jednego polecenia:

PGPASSWORD="mypass" pg_dump mydb > mydb.dump
gitaarik
źródło
27
Ustawienie zmiennej środowiskowej PGPASSWORD nie jest zalecaną praktyką w dokumentacji ( postgresql.org/docs/current/static/libpq-envars.html ): Używanie tej zmiennej środowiskowej nie jest zalecane ze względów bezpieczeństwa, ponieważ niektóre systemy operacyjne zezwalają na root użytkowników, aby zobaczyć zmienne środowiskowe procesu za pomocą ps; zamiast tego rozważ użycie pliku ~ / .pgpass
bouchon,
18
To wciąż przydatny komentarz. Istnieje wiele przypadków wdrażania, w których jest to nadal pomocne.
Iain Duncan
1
Zawsze pojawia się błąd „Uwierzytelnianie elementu równorzędnego nie powiodło się dla użytkownika„ nazwa użytkownika ””. Rozwiązaniem było: PGPASSWORD = "mypass" pg_dump -U nazwa użytkownika -h localhost> mydb.dump
Martin Pabst
4
Uważam, że o wiele lepiej jest skonfigurować zmienną środowiskową (gdzie masz kontrolę, gdzie i jak hasło będzie przechowywane), jak w znanej, niezaszyfrowanej lokalizacji. Ta część dokumentu postgresql jest wadliwa i ta odpowiedź jest dobra.
peterh - Przywróć Monikę
1
Moje hasło zawierało „@”. To zadziałało. Nie mogłem wymyślić, jak to zrobić ze postgres://składnią. Nie próbowałem, .pgpassponieważ mój użytkownik postgress nie ma katalogu domowego.
jmathew
136

W przypadku jednowierszowego, takiego jak migracja bazy danych, można użyć --dbnamełańcucha połączenia (w tym hasła), zgodnie z instrukcją pg_dump

W istocie.

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

Uwaga: Upewnij się, że używasz opcji --dbnamezamiast krótszej -di używasz poprawnego prefiksu URI, postgresql://lub postgres://.

Ogólny formularz URI to:

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

Najlepsza praktyka w twoim przypadku (powtarzalne zadanie w cronie) nie powinno się tego robić z powodu problemów z bezpieczeństwem. Gdyby nie .pgpassplik, zapisałbym ciąg połączenia jako zmienną środowiskową.

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

więc miejcie w swoim crontabie

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

Josue Alexander Ibarra
źródło
Wersja 9.1 Postgre wyświetla nieznaną opcję dla dbname
podobnie
Zostało to przetestowane w wersjach 9.4 i 9.3 odpowiednio na arch i RHEL. czy możesz opublikować ciąg połączenia? oczywiście anonimowe.
Josue Alexander Ibarra
Dzięki, @JosueIbarra. Testy zakończyły się powodzeniem na PostgreSQL 9.3, Ubuntu 14.04.
Cao Minh Tu
1
@EntryLevelR musisz potokować wyjście do pliku, aby go zapisać. zobacz to istotne pytanie askubuntu.com/questions/420981/...
Josue Alexander Ibarra
4
to powinna być zaakceptowana odpowiedź. Jedna wkładka, przezroczysta.
swdev,
48
$ PGPASSWORD="mypass" pg_dump -i -h localhost -p 5432 -U username -F c -b -v -f dumpfilename.dump databasename
Francisco Luz
źródło
Ładne, ale niestety nie działa na mnie, mam „query failed: BŁĄD: brak dostępu do relacji direction_lookup”
James T Snell
@Doc próbowałeś dać niezbędne uprawnienia użytkownikowi pg?
Francisco Luz
33

Ta jedna linijka pomaga mi podczas tworzenia zrzutu pojedynczej bazy danych.

PGPASSWORD="yourpassword" pg_dump -U postgres -h localhost mydb > mydb.pgsql
Aarvy
źródło
1
bardzo pomógł ... thnxxx
ronit
19

@Josue Alexander Ibarra odpowiedź działa na centos 7 i wersji 9.5, jeśli --dbname nie zostanie przekazane.

pg_dump postgresql://username:[email protected]:5432/mydatabase 
Jauyzed
źródło
1
Masz rację, tak to powinno wyglądać. Myślę, że kilka lat temu nie tak było z moją konfiguracją powłoki. Dlatego tak ważne było dla mnie użycie--dbname
Josue Alexander Ibarra
7

Pamiętaj, że w systemie Windows pgpass.confplik musi znajdować się w następującym folderze:

%APPDATA%\postgresql\pgpass.conf

jeśli w postgresqlfolderze nie ma %APPDATA%folderu, utwórz go.

pgpass.confzawartość pliku jest coś takiego:

localhost:5432:dbname:dbusername:dbpassword

Twoje zdrowie

Fernando Meneses Gomes
źródło
4

Popraw mnie, jeśli się mylę, ale jeśli użytkownik systemu jest taki sam jak użytkownik bazy danych, PostgreSQL nie poprosi o hasło - polega na systemie do uwierzytelnienia. Może to być kwestia konfiguracji.

Tak więc, gdy chciałem właściciela bazy danych postgresdo tworzenia kopii zapasowych swoich bazach danych każdej nocy, mogę stworzyć crontab dla niego: crontab -e -u postgres. Oczywiście postgresnależałoby zezwolić na wykonywanie zadań crona; dlatego musi być wymieniony w /etc/cron.allowlub /etc/cron.denymusi być pusty.

Tobiasz
źródło
W pewnym sensie jesteś tutaj. Domyślna konfiguracja Postgres używa uwierzytelnienia TRUST dla lokalnych kont systemowych. Jednak większość konfiguracji produkcyjnych pozbywa się tego bloku zaraz po zainstalowaniu RDBMS.
Jacek Prucia,
4

Wykonaj kopię zapasową przez ssh za pomocą hasła przy użyciu tymczasowych poświadczeń .pgpass i przekaż do 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

Wystarczy zastąpić pierwszą parę linii konfiguracji tym, czego potrzebujesz - oczywiście. Dla tych, którzy nie są zainteresowani częścią zapasową S3, wyjmij ją - oczywiście.

Skrypt ten usuwa później poświadczenia, .pgpassponieważ w niektórych środowiskach domyślny użytkownik SSH może sudo bez hasła, na przykład wystąpienie EC2 z ubuntuużytkownikiem, więc używanie .pgpassinnego konta hosta w celu zabezpieczenia tych poświadczeń może być bezcelowe.

MikeM
źródło
Hasło zostanie zalogowane do terminala w historyten sposób, nie?
mpen
1
@mpen Lokalnie, tak. Zdalnie, nie. W moim przypadku jest OK mieć w mojej lokalnej historii, ponieważ jest to bezpieczna maszyna wirtualna, która nie pozwala na zdalny dostęp. Jeśli w twoim przypadku nie jest OK, po prostu zrób history -c. Korzystając z Jenkins, użyj Inject passwords to the build as environment variablesopcji, aby hasło było maskowane
MikeM
4

Jak szczegółowo opisano w tym poście na blogu , istnieją dwa sposoby nieinteraktywnego podania hasła do narzędzi PostgreSQL, takich jak polecenie „pg_dump”: użycie pliku „.pgpass” lub użycie zmiennej środowiskowej „PGPASSWORD” .

manfall19
źródło
-1

Innym (prawdopodobnie nie bezpiecznym) sposobem na podanie hasła jest przekierowanie wejściowe, tj. Wywołanie

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

szymond
źródło
W kwestii bezpieczeństwa - plik ten musiałby być czytelny tylko dla zamierzonego użytkownika (użytkowników); jednak każdy z prawami root może zmienić ustawienia bezpieczeństwa, a tym samym odczytać niezaszyfrowane hasło. Więc tak, to niepewne ...
Tobias
3
@Tobias czy jest jakaś alternatywa? Wydawałoby się, że każdy z prawami roota zawsze może zobaczyć hasło bez względu na technikę inną niż interaktywne wprowadzanie hasła (pytanie dotyczy crona). postgresql.org/docs/9.3/static/auth-methods.html#GSSAPI-AUTH wspomina o GSSAPI obsługującym logowanie jednokrotne, ale nie ma wzmianki, czy to działa nieinteraktywnie.
Ross Bradbury,
4
Każdy z prawami root może również przeczytać .pgpass, który jest zalecanym sposobem. Dlatego nie uważałbym dostępu do konta root za zagrożenie bezpieczeństwa.
maks.
-1

Możesz przekazać hasło bezpośrednio do pg_dump, używając następujących poleceń:

pg_dump "host=localhost port=5432 dbname=mydb user=myuser password=mypass" > mydb_export.sql
Larry Spence
źródło
Witamy w Stack Overflow! Twoja odpowiedź może zadziałać, ale ma poważne konsekwencje dla bezpieczeństwa. Argumenty polecenia są widoczne w ps (1) , więc jeśli proces monitoruje ps (1), hasło jest zagrożone.
Jonathan Rosa
-4

według mnie najłatwiejszy sposób: edytujesz główny plik konfiguracyjny postgres: pg_hba.conf tam musisz dodać następujący wiersz:

host <you_db_name> <you_db_owner> 127.0.0.1/32 trust

a potem musisz zacząć cron w ten sposób:

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

i działało bez hasła

Dofri
źródło
Właśnie zniszczyłeś bezpieczeństwo systemu. OK jak na dev box, ale nic więcej.
Theodore R. Smith