Postgresql: Tập lệnh thực thi psql bằng mật khẩu


274

Làm thế nào tôi có thể gọi psql để nó không nhắc mật khẩu ?

Đây là những gì tôi có:

psql -Umyuser < myscript.sql

Tuy nhiên, tôi không thể tìm thấy đối số vượt qua mật khẩu và vì vậy psql luôn nhắc nhở về nó.


4
Cuối cùng tôi đã đi đến biến môi trường PGPASSWORD. Điều này phù hợp với usecase của tôi hoàn hảo. Đơn giản và khép kín trong kịch bản.
Axel Fontaine

Chỉ cần tìm thấy postgresguide.com/utilities/psql.html
D_C

Câu trả lời:


315

Có một số cách để xác thực với PostgreSQL. Bạn có thể muốn điều tra các lựa chọn thay thế để xác thực mật khẩu tại https://www.postgresql.org/docs/civerse/static/client-authentication.html .

Để trả lời câu hỏi của bạn, có một vài cách cung cấp mật khẩu để xác thực dựa trên mật khẩu. Cách rõ ràng là thông qua dấu nhắc mật khẩu. Thay vào đó, bạn có thể cung cấp mật khẩu trong tệp pgpass hoặc thông qua PGPASSWORDbiến môi trường. Xem những điều này:

Không có tùy chọn để cung cấp mật khẩu dưới dạng đối số dòng lệnh vì thông tin đó thường có sẵn cho tất cả người dùng và do đó không an toàn. Tuy nhiên, trong môi trường Linux / Unix, bạn có thể cung cấp một biến môi trường cho một lệnh như thế này:

PGPASSWORD=yourpass psql ...

11
Tôi nghĩ PGPASSWORD không được dùng nữa nhưng vẫn hoạt động, btw. Chỉ cần FYI
Scott Marlowe

35
Đúng, nó không được dùng nữa (và được ghi chú trong một trong các liên kết). Kể từ khi nó xuất hiện, có lẽ cũng đáng lưu ý rằng sự phản đối đang bị tranh cãi gay gắt vì nó cực kỳ hữu ích cho nhiều người nhưng vẫn có thể được sử dụng trong một số trường hợp mà không cần lo ngại về bảo mật nghiêm trọng. Đối với tôi, dường như không tệ hơn việc lưu trữ .pgpass trên hệ thống tệp NFS. Tôi sử dụng PGPASSWORD thường xuyên.
lừa

1
ý tưởng rằng thông tin dòng lệnh là "có sẵn cho tất cả người dùng" dựa trên các giả định lỗi thời về các hệ thống nhiều người dùng và không áp dụng trong hầu hết các môi trường hiện đại, nơi các hệ thống chỉ chạy một ứng dụng và tất cả đều tự động
Alex R

159
PGPASSWORD=[your password] psql -Umyuser < myscript.sql

1
điều này cũng hoạt động trong terraform. bạn, bạn của tôi, là một phao cứu sinh
wildthing81

67

Bạn có thể thêm dòng lệnh này khi bắt đầu tập lệnh của mình:

set PGPASSWORD=[your password]

24
trong trường hợp của tôi, lệnh set không hoạt động nhưng export PGPASSWORD=[password]đã hoạt động
Can Kavaklıoğlu

nó không hoạt động trong shell script. Tôi đang sử dụng nó #!/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
Cố gắng không sử dụng không gian, ví dụ. PGPASSWORD=password.
Ariejan

48

Nếu bạn dự định có nhiều kết nối máy chủ / cơ sở dữ liệu, tệp ~ / .pgpass là cách để sử dụng.

Các bước:

  1. Tạo tập tin bằng cách sử dụng vim ~/.pgpasshoặc tương tự. Nhập thông tin của bạn theo định dạng sau: hostname:port:database:username:passwordKhông thêm dấu ngoặc kép xung quanh các giá trị trường của bạn. Bạn cũng có thể sử dụng * làm ký tự đại diện cho các trường cổng / cơ sở dữ liệu của mình.
  2. Bạn phải chmod 0600 ~/.pgpassđể nó không bị âm thầm bỏ qua bởi psql.
  3. Tạo một bí danh trong hồ sơ bash chạy lệnh psql cho bạn. Ví dụ: alias postygresy='psql --host hostname database_name -U username'Các giá trị phải khớp với các giá trị mà bạn đã nhập vào tệp ~ / .pgpass.
  4. Nguồn hồ sơ bash của bạn với . ~/.bashrchoặc tương tự.
  5. Nhập bí danh của bạn từ dòng lệnh.

Lưu ý rằng nếu bạn có bộ biến PGPASSWORD = '' xuất, nó sẽ được ưu tiên hơn tệp.


1
Bạn phải làm một chmod 600tập tin, nếu không psqlsẽ âm thầm bỏ qua nó (theo các tài liệu).
RichVel

33

Đây có thể là một câu hỏi cũ, nhưng có một phương pháp thay thế mà bạn có thể sử dụng mà không ai đề cập đến. Có thể chỉ định mật khẩu trực tiếp trong URI kết nối. Các tài liệu có thể được tìm thấy ở đây , thay thế ở đây .

Bạn có thể cung cấp tên người dùng và mật khẩu của mình trực tiếp trong URI kết nối được cung cấp cho psql:

# postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]
psql postgresql://username:password@localhost:5432/mydb

2
Postrgres 9.3 bỏ qua biến môi trườngPGPASSWORD
david.perez

14

Nếu bạn gặp sự cố trên các cửa sổ như tôi (Tôi đang sử dụng Windows 7 64-bit) và set PGPASSWORD=[Password]không hoạt động.

Sau đó, như Kavaklioglu đã nói trong một trong những bình luận,

export PGPASSWORD=[password]

Bạn sẽ cần lưu phần này ở đầu tệp hoặc trước bất kỳ cách sử dụng nào để tập trước khi được gọi.

Chắc chắn không hoạt động trên windows :)


1
export PGPASSWORD=[password]hoàn toàn không hoạt động với tôi bằng cách sử dụng dòng lệnh (cmd.exe). Bạn có chắc chắn rằng bạn không sử dụng cygwin hoặc một cái gì đó tương tự?
Devin Snyder

Chỉ hoạt động với cl, bạn đã thêm nó vào tập tin phải không? Bây giờ chỉ cần gõ nó vào lệnh?
Jamie Hutber

Bạn có thể sử dụng nó trong môi trường linux / mac, đối với windows, tôi nghĩ bạn nên tìm cách xuất biến môi trường này.
Pengfei.X

Vì vậy, hãy thêm mật khẩu toàn cầu ... Đó cũng là một ý tưởng thú vị
Jamie Hutber 5/03/2015


7

Với những lo ngại về bảo mật về việc sử dụng biến môi trường PGPASSWORD, tôi nghĩ giải pháp tổng thể tốt nhất là như sau:

  1. Viết tập tin pgpass tạm thời của riêng bạn với mật khẩu bạn muốn sử dụng.
  2. Sử dụng biến môi trường PGPASSFILE để báo cho psql sử dụng tệp đó.
  3. Xóa tệp pgpass tạm thời

Có một vài điểm lưu ý ở đây. Bước 1 là ở đó để tránh mucking với tập tin ~ / .pgpass của người dùng có thể tồn tại. Bạn cũng phải đảm bảo rằng tệp có quyền 0600 trở xuống.

Một số đã đề xuất tận dụng bash để tắt phím này như sau:

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

Điều này sử dụng cú pháp <() để tránh cần phải ghi dữ liệu vào một tệp thực tế. Nhưng nó không hoạt động vì psql kiểm tra tập tin nào đang được sử dụng và sẽ đưa ra một lỗi như thế này:

WARNING: password file "/dev/fd/63" is not a plain file

Một ví dụ hoạt động của phương pháp này xuất hiện trong stackoverflow.com/a/40614592/3696363 - một câu trả lời khác cho câu hỏi này.
Eliyahu Skoczylas

Mặc dù người dùng này không thực sự yêu cầu điều tương tự mà tôi đang tìm kiếm, tôi sẽ nói rằng cách tiếp cận này không phù hợp. Khi sử dụng cú pháp PGPASSFILE = <(bất cứ điều gì), bạn có thể thực hiện những việc như giải mã một tệp và chỉ có nó trong bộ mô tả tệp được tạo. Bằng cách viết tệp tạm thời, về cơ bản, bạn không giải quyết được vấn đề có tệp trên đĩa có thông tin xác thực. Thật không vui khi đối phó với các quy tắc công nghiệp tùy tiện như thế, nhưng đó là điều mà nhiều người đối phó.
Desidero

7

Nó có thể được thực hiện đơn giản bằng cách sử dụng PGPASSWORD. Tôi đang sử dụng psql 9.5.10. Trong trường hợp của bạn, giải pháp sẽ là

PGPASSWORD=password psql -U myuser < myscript.sql


5

Dựa trên câu trả lời của mightybyte cho những người không thoải mái với kịch bản shell * nix , đây là một kịch bản hoạt động:

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

Ký hiệu đô la kép ( $$) /tmp/pgpasswd$$ở dòng 2 sẽ thêm số ID quy trình vào tên tệp, để tập lệnh này có thể được chạy nhiều lần, thậm chí đồng thời, không có tác dụng phụ.

Lưu ý việc sử dụng chmodlệnh ở dòng 4 - giống như lỗi " không phải là tệp đơn giản " mà mightybyte đã mô tả, cũng có lỗi " quyền " nếu điều này không được thực hiện.

Ở dòng 7, bạn sẽ không phải sử dụng cờ -hmyserver , -pmyport hoặc -Ujdoe nếu bạn sử dụng mặc định ( localhost : 5432 ) và chỉ có một người dùng cơ sở dữ liệu. Đối với nhiều người dùng, (nhưng kết nối mặc định) thay đổi dòng đó thành

psql mydb jdoe

Đừng quên để tập lệnh thực thi với

chmod +x runpsql( hoặc bất cứ điều gì bạn gọi là tệp script )

CẬP NHẬT:

Tôi đã lấy lời khuyên của RichVel và làm cho tập tin không thể đọc được trước khi đặt mật khẩu vào đó. Điều đó đóng một lỗ hổng bảo mật nhẹ. Cảm ơn!


4
Bạn có thể sử dụng mktempđể tạo một tệp tạm thời thay vì đưa ra sơ đồ đặt tên của riêng bạn. Nó tạo ra một tệp tạm thời mới (được đặt tên giống như /tmp/tmp.ITXUNYgiNhtrong Linux và /var/folders/xx/7gws2yy91vn9_t2lb8jcr2gr0000gn/T/tmp.QmbVOQk4trên MacOS X) và in tên của nó thành thiết bị xuất chuẩn.
Ivan Kolmychek

1
Vấn đề bảo mật Tốt nhất là thực hiện chmod 600sau khi tạo tệp, nhưng trước khi ghi mật khẩu vào đó. Như đã viết, một tập lệnh độc hại trên máy chủ có thể liên tục cố gắng đọc các tệp có định dạng này và đôi khi sẽ thành công trong việc lấy mật khẩu. Ngoài ra, nếu kịch bản này bị gián đoạn vì một số lý do, tệp sẽ được để lại trên đĩa - viết traptrình xử lý shell sẽ giải quyết vấn đề này. Cho rằng việc viết một tập lệnh an toàn như thế này không phải là chuyện nhỏ, tôi khuyên bạn nên sử dụng export PGPASSWORDthay thế.
RichVel

Cảm ơn, @RichVel đã chỉ ra lỗ hổng bảo mật nhỏ đó. Chạm vào tạo và đặt tệp ở chế độ riêng tư trước khi đặt mật khẩu vào đó là một cải tiến rõ ràng. Loại giải pháp này là cần thiết vì PGPASSWORDđã bị phản đối trong 9.3.
Eliyahu Skoczylas

Một số tài liệu nói rằng nó không được chấp nhận nhưng như đã đề cập trong một nhận xét trong phần hỏi đáp này , sự phản đối được tranh cãi và nó vẫn hoạt động kể từ Postgres 10.6
RichVel

5

Một cách khác để sử dụng PGPASSWORDbiến môi trường là sử dụng conninfochuỗi theo tài liệu

Một cách khác để chỉ định tham số kết nối là trong chuỗi Conninfo hoặc URI, được sử dụng thay cho tên cơ sở dữ liệu. Cơ chế này cung cấp cho bạn quyền kiểm soát rất rộng đối với kết nối.

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

postgres=>



-1

Tôi thấy rằng, psql hiển thị dấu nhắc mật khẩu ngay cả khi bạn xác định biến PGPASSWORD, nhưng bạn có thể chỉ định tùy chọn -w cho psql để bỏ qua dấu nhắc mật khẩu.


-6

Sử dụng -w trong lệnh: psql -h localhost -p 5432 -U user -w

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.