Postgresql: Skryptowe wykonywanie psql z hasłem

274

Jak mogę wywołać psql, aby nie monitował o hasło ?

Oto co mam:

psql -Umyuser < myscript.sql

Jednak nie mogłem znaleźć argumentu, który przekazuje hasło, dlatego psql zawsze go prosi.

Axel Fontaine
źródło
4
Skończyło się na szukaniu zmiennej środowiskowej PGPASSWORD. To idealnie pasowało do mojej walizki. Prosty i samodzielny w skrypcie.
Axel Fontaine
Właśnie znalazłem ten postgresguide.com/utilities/psql.html
D_C
Możliwy duplikat Jak określić hasło do psql nieinteraktywnie?
Helder Pereira

Odpowiedzi:

315

Istnieje kilka sposobów uwierzytelnienia w PostgreSQL. Możesz sprawdzić alternatywne sposoby uwierzytelniania za pomocą hasła na stronie https://www.postgresql.org/docs/current/static/client-authentication.html .

Aby odpowiedzieć na twoje pytanie, istnieje kilka sposobów podania hasła do uwierzytelnienia opartego na haśle. Oczywistym sposobem jest podanie hasła. Zamiast tego możesz podać hasło w pliku pgpass lub poprzez PGPASSWORDzmienną środowiskową. Zobacz te:

Nie ma opcji podania hasła jako argumentu wiersza poleceń, ponieważ informacje te są często dostępne dla wszystkich użytkowników, a zatem niepewne. Jednak w środowiskach Linux / Unix możesz podać zmienną środowiskową dla jednego polecenia, takiego jak to:

PGPASSWORD=yourpass psql ...
Reece
źródło
11
Myślę, że PGPASSWORD jest przestarzałe, ale nadal działa, przy okazji. Just FYI
Scott Marlowe
35
Tak, jest przestarzałe (i tak zaznaczono w jednym z linków). Ponieważ pojawiło się, prawdopodobnie warto również zauważyć, że wycofanie jest bardzo kwestionowane, ponieważ jest niezwykle przydatne dla wielu osób, ale może być używane w niektórych okolicznościach bez poważnych obaw dotyczących bezpieczeństwa. Wydaje mi się, że nie jest to gorsze niż przechowywanie .pgpass na przykład w systemie plików NFS. Rutynowo używam PGPASSWORD.
Reece
1
idea, że ​​informacje z wiersza poleceń są „dostępne dla wszystkich użytkowników”, opiera się na przestarzałych założeniach dotyczących systemów wieloużytkownikowych i nie ma zastosowania w większości nowoczesnych środowisk, w których systemy uruchamiają tylko jedną aplikację i wszystko jest zautomatyzowane
Alex R
159
PGPASSWORD=[your password] psql -Umyuser < myscript.sql
Greg
źródło
1
działa to również w terraformie. ty, mój przyjacielu,
ratujesz życie
67

Możesz dodać ten wiersz poleceń na początku skryptu:

set PGPASSWORD=[your password]
jbaylina
źródło
24
w moim przypadku polecenie set nie działało, ale export PGPASSWORD=[password]działało
Can Kavaklıoğlu
nie działa w skrypcie powłoki. Używam go #!/bin/sh set PGPASSWORD = postgres psql -h 192.168.3.200 -U postgres incx_um << EOF DELETE FROM usrmgt.user_one_time_codes WHERE time < NOW() - INTERVAL '30 minute' EOF
Govind Gupta
2
Staraj się nie używać spacji, np. PGPASSWORD=password.
Ariejan
48

Jeśli zamierzasz mieć wiele połączeń host / baza danych, najlepszym rozwiązaniem jest plik ~ / .pgpass .

Kroki:

  1. Utwórz plik za pomocą vim ~/.pgpasslub podobnego. Wprowadź informacje w następującym formacie: hostname:port:database:username:passwordNie dodawaj cudzysłowów ciągowych wokół wartości pól. Możesz także użyć * jako symbolu wieloznacznego dla pól portu / bazy danych.
  2. Musisz chmod 0600 ~/.pgpass, aby psql nie ignorował go po cichu.
  3. Utwórz alias w swoim profilu bash, który uruchomi dla ciebie twoje polecenie psql. Na przykład: alias postygresy='psql --host hostname database_name -U username'Wartości powinny być zgodne z wartościami wprowadzonymi do pliku ~ / .pgpass.
  4. Źródło swojego profilu bash z . ~/.bashrclub podobnym.
  5. Wpisz swój alias z wiersza poleceń.

Zauważ, że jeśli masz ustawiony zestaw zmiennych PGPASSWORD = '', będzie on miał pierwszeństwo przed plikiem.

tandy
źródło
1
Musisz zrobić a chmod 600na pliku, w przeciwnym razie psqldyskretnie go zignoruje (zgodnie z dokumentami).
RichVel
33

To może być stare pytanie, ale istnieje alternatywna metoda, której można użyć, o której nikt nie wspomniał. Możliwe jest określenie hasła bezpośrednio w URI połączenia. Dokumentację można znaleźć tutaj lub alternatywnie tutaj .

Możesz podać swoją nazwę użytkownika i hasło bezpośrednio w identyfikatorze URI połączenia podanym w celu psql:

# postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]
psql postgresql://username:password@localhost:5432/mydb
ajxs
źródło
2
Postrgres 9.3 ignoruje zmienną środowiskowąPGPASSWORD
david.perez
14

Jeśli masz problemy w systemie Windows takim jak ja (używam 64-bitowego systemu Windows 7) i set PGPASSWORD=[Password]nie działało.

Następnie, jak powiedział Kavaklioglu w jednym z komentarzy,

export PGPASSWORD=[password]

Będziesz musiał zapisać to na górze pliku lub przed użyciem, więc ustaw go przed wywołaniem.

Z pewnością działa na systemie Windows :)

Jamie Hutber
źródło
1
export PGPASSWORD=[password]w ogóle nie działa przy użyciu wiersza polecenia (cmd.exe). Czy na pewno nie używasz cygwina lub czegoś podobnego?
Devin Snyder,
Działa tylko z cl, dodałeś go do pliku, prawda? Teraz wpisałeś to w poleceniu?
Jamie Hutber,
można używać go w środowisku Linux / Mac, w systemie Windows myślę, że powinieneś znaleźć sposób na wyeksportowanie tej zmiennej środowiskowej.
Pengfei.X
Dodaj globalne hasło ... To także ciekawy pomysł
Jamie Hutber
7

Biorąc pod uwagę obawy dotyczące bezpieczeństwa związane ze stosowaniem zmiennej środowiskowej PGPASSWORD, myślę, że najlepsze ogólne rozwiązanie jest następujące:

  1. Napisz swój tymczasowy plik pgpass z hasłem, którego chcesz użyć.
  2. Użyj zmiennej środowiskowej PGPASSFILE, aby powiedzieć psql, aby używał tego pliku.
  3. Usuń tymczasowy plik pgpass

Jest tu kilka ważnych punktów. Krok 1 ma na celu uniknięcie zmarnowania pliku ~ / .pgpass użytkownika, który może istnieć. Musisz także upewnić się, że plik ma uprawnienia 0600 lub niższe.

Niektórzy sugerują użycie bash do skrótu w następujący sposób:

PGPASSFILE=<(echo myserver:5432:mydb:jdoe:password) psql -h myserver -U jdoe -p 5432 mydb

Korzysta ze składni <(), aby uniknąć konieczności zapisywania danych w rzeczywistym pliku. Ale to nie działa, ponieważ psql sprawdza, który plik jest używany i zgłasza taki błąd:

WARNING: password file "/dev/fd/63" is not a plain file
mightybyte
źródło
Działający przykład tego podejścia pojawia się w stackoverflow.com/a/40614592/3696363 - kolejna odpowiedź na to pytanie.
Eliyahu Skoczylas
Chociaż ten użytkownik tak naprawdę nie prosił o to, czego szukam, powiedziałbym, że podejście nie pasuje. Korzystając ze składni PGPASSFILE = <(cokolwiek), możesz wykonywać takie czynności, jak odszyfrowanie pliku i obecność go tylko w utworzonym deskryptorze pliku. Pisząc plik tymczasowy, nie rozwiązujesz zasadniczo problemu posiadania pliku na dysku z poświadczeniami. Nie jest fajnie radzić sobie z takimi arbitralnymi regułami branżowymi, ale wiele osób ma z tym do czynienia.
Desidero
7

Można to zrobić po prostu za pomocą PGPASSWORD. Używam psql 9.5.10. W twoim przypadku rozwiązaniem byłoby

PGPASSWORD=password psql -U myuser < myscript.sql

pyAddict
źródło
5

Opierając się na odpowiedzi mightybyte dla tych, którzy nie czują się dobrze ze skryptami powłoki * nix , oto działający skrypt:

#!/bin/sh
PGPASSFILE=/tmp/pgpasswd$$
touch $PGPASSFILE
chmod 600 $PGPASSFILE
echo "myserver:5432:mydb:jdoe:password" > $PGPASSFILE
export PGPASSFILE
psql mydb
rm $PGPASSFILE

Podwójny znak dolara ( $$) w /tmp/pgpasswd$$wierszu 2 dołącza numer identyfikacyjny procesu do nazwy pliku, dzięki czemu skrypt może być uruchamiany więcej niż jeden raz, nawet jednocześnie, bez skutków ubocznych.

Zwróć uwagę na użycie chmodpolecenia w wierszu 4 - podobnie jak opisany przez mightybyte błąd „ zwykły plik ” , istnieje również błąd „ uprawnień ”, jeśli nie zostanie to zrobione.

W linii 7 nie musisz używać flagi -hmyserver , -pmyport ani -Ujdoe, jeśli używasz wartości domyślnych ( localhost : 5432 ) i masz tylko jednego użytkownika bazy danych. W przypadku wielu użytkowników (ale domyślne połączenie) zmień tę linię na

psql mydb jdoe

Nie zapomnij, aby skrypt wykonywalny z

chmod +x runpsql( lub jakkolwiek nazwałeś plik skryptu )

AKTUALIZACJA:

Wziąłem RichVel porady „s i wykonany plik nieczytelny przed uruchomieniem hasło do niego. To zamyka niewielką lukę bezpieczeństwa. Dzięki!

Eliyahu Skoczylas
źródło
4
Możesz użyć mktempdo utworzenia pliku tymczasowego zamiast tworzenia własnego schematu nazewnictwa. Tworzy nowy plik tymczasowy (o nazwie podobnej /tmp/tmp.ITXUNYgiNhdo Linuxa i /var/folders/xx/7gws2yy91vn9_t2lb8jcr2gr0000gn/T/tmp.QmbVOQk4MacOS X) i wypisuje jego nazwę na standardowe wyjście.
Ivan Kolmychek
1
Problem bezpieczeństwa Najlepiej zrobić to chmod 600po utworzeniu pliku, ale przed zapisaniem hasła do niego. Jak napisano, złośliwy skrypt na serwerze może nieustannie próbować czytać pliki tego formatu, a czasem może uzyskać hasło. Ponadto, jeśli ten skrypt zostanie z jakiegoś powodu przerwany, plik zostałby pozostawiony na dysku - napisanie trapprocedury obsługi powłoki rozwiązałoby ten problem. Biorąc pod uwagę, że napisanie takiego bezpiecznego skryptu nie jest trywialne, zalecamy użycie export PGPASSWORDzamiast tego.
RichVel
Dzięki, @RichVel za wskazanie tej małej dziury w zabezpieczeniach. Dotknij, aby utworzyć i ustawić plik jako prywatny, zanim umieścisz w nim hasło, to zdecydowane ulepszenie. Tego rodzaju rozwiązanie jest potrzebne, ponieważ PGPASSWORDzostało przestarzałe w 9.3.
Eliyahu Skoczylas
Niektóre dokumenty mówią, że jest przestarzałe, ale jak wspomniano w komentarzu do tego pytania i odpowiedzi , wycofanie jest kwestionowane i nadal działa od Postgres 10.6
RichVel 11.04.19
5

Alternatywą dla używania PGPASSWORDzmiennej środowiskowej jest użycie conninfołańcucha zgodnie z dokumentacją

Alternatywnym sposobem określenia parametrów połączenia jest ciąg Conninfo lub identyfikator URI, który jest używany zamiast nazwy bazy danych. Ten mechanizm zapewnia bardzo szeroką kontrolę nad połączeniem.

$ psql "host=<server> port=5432 dbname=<db> user=<user> password=<password>"

postgres=>
ubi
źródło
-1

Uważam, że psql wyświetla monit o podanie hasła, nawet jeśli zdefiniujesz zmienną PGPASSWORD, ale możesz podać opcję -w, aby psql pomijał monit o podanie hasła.

Mark Lokshin
źródło
-6

Użyj -w w poleceniu: psql -h localhost -p 5432 -U użytkownik -w

vjOnstack
źródło