Postgresql: ejecución de scripts psql con contraseña

274

¿Cómo puedo llamar a psql para que no solicite una contraseña ?

Esto es lo que tengo:

psql -Umyuser < myscript.sql

Sin embargo, no pude encontrar el argumento que pasa la contraseña, por lo que psql siempre lo solicita.

Axel Fontaine
fuente
44
Terminé yendo por la variable de entorno PGPASSWORD. Esto encajaba perfectamente en mi caso de uso. Simple y autónomo en el guión.
Axel Fontaine
Acabo de encontrar este postgresguide.com/utilities/psql.html
D_C

Respuestas:

315

Hay varias formas de autenticarse en PostgreSQL. Es posible que desee investigar alternativas a la autenticación de contraseña en https://www.postgresql.org/docs/current/static/client-authentication.html .

Para responder a su pregunta, hay algunas formas de proporcionar una contraseña para la autenticación basada en contraseña. La forma obvia es a través de la solicitud de contraseña. En lugar de eso, puede proporcionar la contraseña en un archivo pgpass o mediante la PGPASSWORDvariable de entorno. Ver estos:

No hay ninguna opción para proporcionar la contraseña como argumento de línea de comando porque esa información a menudo está disponible para todos los usuarios y, por lo tanto, no es segura. Sin embargo, en entornos Linux / Unix, puede proporcionar una variable de entorno para un solo comando como este:

PGPASSWORD=yourpass psql ...
Reece
fuente
11
Creo que PGPASSWORD está en desuso pero todavía funciona, por cierto. Solo para tu información
Scott Marlowe
35
Sí, está en desuso (y así se indica en uno de los enlaces). Dado que surgió, probablemente también valga la pena señalar que la desaprobación es muy controvertida porque es extremadamente útil para muchas personas y, sin embargo, puede usarse en algunas circunstancias sin serias preocupaciones de seguridad. Me parece que no es peor que almacenar .pgpass en un sistema de archivos NFS, por ejemplo. Yo uso PGPASSWORD de forma rutinaria.
Reece
1
La idea de que la información de la línea de comandos está "disponible para todos los usuarios" se basa en suposiciones anticuadas sobre sistemas multiusuario y no se aplica en la mayoría de los entornos modernos donde los sistemas solo ejecutan una sola aplicación y todo está automatizado
Alex R
159
PGPASSWORD=[your password] psql -Umyuser < myscript.sql
Greg
fuente
1
esto también funciona en terraform. usted, mi amigo, es un salvavidas
wildthing81
67

Puede agregar esta línea de comando al comienzo de su script:

set PGPASSWORD=[your password]
jbaylina
fuente
24
en mi caso, el comando set no funcionó pero export PGPASSWORD=[password]funcionó
Can Kavaklıoğlu
No funciona en el script de shell. Lo estoy usando #!/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
Intente no usar espacios, por ejemplo. PGPASSWORD=password.
Ariejan
48

Si tiene la intención de tener múltiples conexiones de host / base de datos, el archivo ~ / .pgpass es el camino a seguir.

Pasos:

  1. Cree el archivo usando vim ~/.pgpasso similar. Ingrese su información en el siguiente formato: hostname:port:database:username:passwordNo agregue comillas alrededor de los valores de su campo. También puede usar * como comodín para sus campos de puerto / base de datos.
  2. Debes hacerlo chmod 0600 ~/.pgpasspara que psql no lo ignore en silencio.
  3. Cree un alias en su perfil bash que ejecute su comando psql por usted. Por ejemplo: alias postygresy='psql --host hostname database_name -U username'los valores deben coincidir con los que ingresó en el archivo ~ / .pgpass.
  4. Obtenga su perfil de bash con . ~/.bashrco similar.
  5. Escriba su alias desde la línea de comando.

Tenga en cuenta que si tiene un conjunto de variables PGPASSWORD = '' de exportación, tendrá prioridad sobre el archivo.

tandy
fuente
1
Debe hacer un chmod 600en el archivo, de lo contrario psqllo ignorará en silencio (de acuerdo con los documentos).
RichVel
33

Esta podría ser una pregunta antigua, pero hay un método alternativo que puede usar que nadie ha mencionado. Es posible especificar la contraseña directamente en el URI de conexión. La documentación se puede encontrar aquí , alternativamente aquí .

Puede proporcionar su nombre de usuario y contraseña directamente en el URI de conexión proporcionado a psql:

# postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]
psql postgresql://username:password@localhost:5432/mydb
ajxs
fuente
2
Postrgres 9.3 ignora la variable de entornoPGPASSWORD
david.perez
14

Si tiene problemas en Windows como yo (estoy usando Windows 7 de 64 bits) y set PGPASSWORD=[Password]no funcionó.

Entonces, como dijo Kavaklioglu en uno de los comentarios,

export PGPASSWORD=[password]

Tendrá que guardar esto en la parte superior del archivo, o antes de cualquier uso, por lo que se establece antes de ser llamado.

Ciertamente funciona en Windows :)

Jamie Hutber
fuente
1
export PGPASSWORD=[password]no funciona para mí usando la línea de comando (cmd.exe) en absoluto. ¿Estás seguro de que no estabas usando cygwin o algo similar?
Devin Snyder
Solo funciona con cl, lo agregaste al archivo, ¿verdad? ¿Ahora lo escribiste al mando?
Jamie Hutber
está bien usarlo en un entorno Linux / Mac, para Windows, creo que debería encontrar una manera de exportar esta variable de entorno.
Pengfei.X
Así que agregue una contraseña global ... Esa también es una idea interesante
Jamie Hutber
7

Dadas las preocupaciones de seguridad sobre el uso de la variable de entorno PGPASSWORD, creo que la mejor solución general es la siguiente:

  1. Escriba su propio archivo pgpass temporal con la contraseña que desea usar.
  2. Use la variable de entorno PGPASSFILE para indicarle a psql que use ese archivo.
  3. Eliminar el archivo temporal pgpass

Hay un par de puntos de nota aquí. El paso 1 está ahí para evitar la intrusión con el archivo ~ / .pgpass del usuario que pueda existir. También debe asegurarse de que el archivo tenga permisos 0600 o menos.

Algunos han sugerido aprovechar bash para atajar esto de la siguiente manera:

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

Esto usa la sintaxis <() para evitar la necesidad de escribir los datos en un archivo real. Pero no funciona porque psql comprueba qué archivo se está utilizando y arrojará un error como este:

WARNING: password file "/dev/fd/63" is not a plain file
mightybyte
fuente
Un ejemplo práctico de este enfoque aparece en stackoverflow.com/a/40614592/3696363 , otra respuesta a esta pregunta.
Eliyahu Skoczylas
Aunque este usuario realmente no pidió lo mismo que yo estaba buscando, diría que el enfoque no coincide. Al usar la sintaxis PGPASSFILE = <(lo que sea), puede hacer cosas como descifrar un archivo y solo tenerlo presente en el descriptor de archivo que se crea. Al escribir un archivo temporal, no está resolviendo fundamentalmente el problema de tener un archivo en el disco con credenciales. No es divertido lidiar con reglas arbitrarias de la industria como esa, pero es algo con lo que muchas personas lidian.
Desidero
7

Se puede hacer simplemente usando PGPASSWORD. Estoy usando psql 9.5.10. En su caso la solución sería

PGPASSWORD=password psql -U myuser < myscript.sql

pyAddict
fuente
5

Basándose en la respuesta de mightybyte para aquellos que no se sienten cómodos con las secuencias de comandos de shell * nix , aquí hay una secuencia de comandos que funciona:

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

El signo de dólar doble ( $$) en la /tmp/pgpasswd$$línea 2 agrega el número de ID del proceso al nombre del archivo, de modo que este script se puede ejecutar más de una vez, incluso simultáneamente, sin efectos secundarios.

Tenga en cuenta el uso del chmodcomando en la línea 4: al igual que el error " no es un archivo sin formato " que podría describir byybyte , también hay un error de " permisos " si esto no se hace.

En la línea 7, no tendrá que usar el indicador -hmyserver , -pmyport o -Ujdoe si usa los valores predeterminados ( localhost : 5432 ) y solo tiene un usuario de la base de datos. Para varios usuarios, (pero la conexión predeterminada) cambie esa línea a

psql mydb jdoe

No olvide hacer que el script sea ejecutable con

chmod +x runpsql( o como se llame el archivo de script )

ACTUALIZAR:

Tomé RichVel consejos 's e hice el archivo ilegible antes de poner la contraseña en él. Eso cierra un pequeño agujero de seguridad. ¡Gracias!

Eliyahu Skoczylas
fuente
44
Puede usar mktemppara crear un archivo temporal en lugar de crear su propio esquema de nombres. Crea un nuevo archivo temporal (llamado algo así como /tmp/tmp.ITXUNYgiNhen Linux y /var/folders/xx/7gws2yy91vn9_t2lb8jcr2gr0000gn/T/tmp.QmbVOQk4MacOS X) e imprime su nombre en stdout.
Ivan Kolmychek
1
Problema de seguridad Es mejor hacerlo chmod 600después de crear el archivo, pero antes de escribirle la contraseña. Tal como está escrito, una secuencia de comandos maliciosa en el servidor podría intentar continuamente leer archivos de este formato y, a veces, podría obtener la contraseña. Además, si esta secuencia de comandos se interrumpe por alguna razón, el archivo se dejaría en el disco; escribir un trapcontrolador de shell resolvería esto. Dado que no es trivial escribir un script seguro como este, recomiendo usar en su export PGPASSWORDlugar.
RichVel
Gracias, @RichVel por señalar ese pequeño agujero de seguridad. Toque crear y hacer que el archivo sea privado antes de ingresar la contraseña es una mejora definitiva. Este tipo de solución es necesaria porque PGPASSWORDha quedado en desuso en 9.3.
Eliyahu Skoczylas
Algunos de los documentos dicen que está en desuso, pero como se mencionó en un comentario en estas preguntas y respuestas , la desaprobación está en disputa y todavía funciona a partir de Postgres 10.6
RichVel
5

Una alternativa al uso de PGPASSWORDla variable de entorno es usar una conninfocadena de acuerdo con la documentación

Una forma alternativa de especificar los parámetros de conexión es en una cadena de información o un URI, que se utiliza en lugar de un nombre de base de datos. Este mecanismo le brinda un control muy amplio sobre la conexión.

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

postgres=>
ubi
fuente
-1

Creo que psql muestra la solicitud de contraseña incluso si define la variable PGPASSWORD, pero puede especificar la opción -w para que psql omita la solicitud de contraseña.

Mark Lokshin
fuente
-6

Use -w en el comando: psql -h localhost -p 5432 -U usuario -w

vjOnstack
fuente