¿Cómo comprobar si existe un usuario de postgres?

89

createuserpermite la creación de un usuario (ROLE) en PostgreSQL. ¿Existe una forma sencilla de comprobar si ese usuario (nombre) ya existe? De lo contrario, createuser regresa con un error:

createuser: creation of new role failed: ERROR:  role "USR_NAME" already exists

ACTUALIZACIÓN: la solución debería ser ejecutable desde el shell preferiblemente, para que sea más fácil de automatizar dentro de un script.

m33lky
fuente

Respuestas:

161
SELECT 1 FROM pg_roles WHERE rolname='USR_NAME'

Y en términos de línea de comando (gracias a Erwin):

psql postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='USR_NAME'"

Rinde 1 si se encuentra y nada más.

Es decir:

psql postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='USR_NAME'" | grep -q 1 || createuser ...
Michael Krelin - hacker
fuente
¿Recuerda cuál es la utilidad de línea de comandos incorporada para ejecutar SQL? Al final, preferiría ejecutar y recuperar el resultado del shell si es posible.
m33lky
1
psqles el comando. Pero si está hablando createuserde la utilidad de línea de comando (obviamente lo hace, no noté la falta de espacio create useral principio), entonces puede ser más fácil simplemente ignorar el estado de salida y redirigir la salida a /dev/null.
Michael Krelin - hacker
2
@ m33lky: O usted podría probar el valor de retorno de este comando en el shell (como usuario postgres): psql postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='USR_NAME'". Rinde 1si se encuentra y nada más.
Erwin Brandstetter
1
Jaja, lo que acabo de una manera poco más fea: echo "SELECT rolname FROM pg_roles WHERE rolname='USR_NAME';" | psql | grep -c USR_NAME. Agregue su solución como respuesta sin "postgres" después de psql.
m33lky
2
@ m33lky: Solo escribí un comentario, porque creo que Michael se merece el crédito por este. Contribuyó con la parte principal. Y demostró ser un buen deportista en el pasado. :) ¿Quizás Michael quiere incorporarlo en su respuesta?
Erwin Brandstetter
5

Siguiendo la misma idea que para comprobar si existe una base de datos

psql -t -c '\du' | cut -d \| -f 1 | grep -qw <user_to_check>

y puedes usarlo en un script como este:

if psql -t -c '\du' | cut -d \| -f 1 | grep -qw <user_to_check>; then
    # user exists
    # $? is 0
else
    # ruh-roh
    # $? is 1
fi
mate
fuente
Esto generaría un resultado de consulta más grande que answer stackoverflow.com/a/8546783/107158 . Sin embargo, a diferencia de esa respuesta, esta sobreviviría a un cambio de nombre a la tabla del sistema pg_roles, pero no a un cambio en el comando \du. ¿Cuál es más probable que no cambie?
Derek Mahar
3

Espero que esto ayude a aquellos de ustedes que podrían estar haciendo esto en Python .
Creé un script / solución de trabajo completo en un GitHubGist; consulte la URL debajo de este fragmento de código.

# ref: /programming/8546759/how-to-check-if-a-postgres-user-exists
check_user_cmd = ("SELECT 1 FROM pg_roles WHERE rolname='%s'" % (deis_app_user))

# our create role/user command and vars
create_user_cmd = ("CREATE ROLE %s WITH LOGIN CREATEDB PASSWORD '%s'" % (deis_app_user, deis_app_passwd))

# ref: /programming/37488175/simplify-database-psycopg2-usage-by-creating-a-module
class RdsCreds():
    def __init__(self):
        self.conn = psycopg2.connect("dbname=%s user=%s host=%s password=%s" % (admin_db_name, admin_db_user, db_host, admin_db_pass))
        self.conn.set_isolation_level(0)
        self.cur = self.conn.cursor()

    def query(self, query):
        self.cur.execute(query)
        return self.cur.rowcount > 0

    def close(self):
        self.cur.close()
        self.conn.close()

db = RdsCreds()
user_exists = db.query(check_user_cmd)

# PostgreSQL currently has no 'create role if not exists'
# So, we only want to create the role/user if not exists 
if (user_exists) is True:
    print("%s user_exists: %s" % (deis_app_user, user_exists))
    print("Idempotent: No credential modifications required. Exiting...")
    db.close()
else:
    print("%s user_exists: %s" % (deis_app_user, user_exists))
    print("Creating %s user now" % (deis_app_user))
    db.query(create_user_cmd)
    user_exists = db.query(check_user_cmd)
    db.close()
    print("%s user_exists: %s" % (deis_app_user, user_exists))

Proporciona funciones / usuarios remotos idempotentes (RDS) PostgreSQL desde python sin módulos CM, etc.

cmcc
fuente
1

psql -qtA -c "\du USR_NAME" | cut -d "|" -f 1

[[ -n $(psql -qtA -c "\du ${1}" | cut -d "|" -f 1) ]] && echo "exists" || echo "does not exist"

Pascal Polleunus
fuente