Jak sprawdzić, czy istnieje użytkownik postgres?

89

createuserumożliwia utworzenie użytkownika (ROLA) w PostgreSQL. Czy istnieje prosty sposób sprawdzenia, czy ten użytkownik (nazwa) już istnieje? W przeciwnym razie createuser zwraca z błędem:

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

AKTUALIZACJA: Rozwiązanie powinno być najlepiej wykonywalne z powłoki, aby łatwiej było zautomatyzować wewnątrz skryptu.

m33lky
źródło

Odpowiedzi:

161
SELECT 1 FROM pg_roles WHERE rolname='USR_NAME'

A jeśli chodzi o linię poleceń (dzięki Erwinowi):

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

Daje 1, jeśli zostanie znaleziony i nic więcej.

To jest:

psql postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='USR_NAME'" | grep -q 1 || createuser ...
Michael Krelin - haker
źródło
Czy pamiętasz, jakie jest wbudowane narzędzie wiersza poleceń do wykonywania SQL? W końcu wolałbym wykonać i odzyskać wynik z powłoki, jeśli to możliwe.
m33lky
1
psqljest rozkazem. Ale jeśli mówisz o createusernarzędziu wiersza poleceń (oczywiście robisz, na początku nie zauważyłem braku miejsca create user), może być łatwiej po prostu zignorować stan wyjścia i przekierować dane wyjściowe do /dev/null.
Michael Krelin - haker
2
@ m33lky: Albo można przetestować zwracanej wartości tego polecenia w powłoce (jako użytkownik postgres) psql postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='USR_NAME'". Plony, 1jeśli zostaną znalezione i nic więcej.
Erwin Brandstetter
1
Haha, ja po prostu nie że w nieco bardziej brzydki sposób: echo "SELECT rolname FROM pg_roles WHERE rolname='USR_NAME';" | psql | grep -c USR_NAME. Dodaj swoje rozwiązanie jako odpowiedź bez "postgres" po psql.
m33lky
2
@ m33lky: Napisałem tylko komentarz, ponieważ myślę, że Michael zasługuje na uznanie w tej sprawie. Wniósł główną część. W przeszłości okazał się dobrym sportem. :) Może Michael chce włączyć to do swojej odpowiedzi?
Erwin Brandstetter
5

Idąc tym samym pomysłem, co sprawdzić, czy baza danych istnieje

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

i możesz go użyć w skrypcie takim jak ten:

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
matowe
źródło
Spowoduje to wygenerowanie większego wyniku zapytania niż odpowiedź stackoverflow.com/a/8546783/107158 . Jednak w przeciwieństwie do tej odpowiedzi, ta przetrwałaby zmianę nazwy tabeli systemowej pg_roles, ale nie zmianę polecenia \du. Co najprawdopodobniej się nie zmieni?
Derek Mahar
3

Mam nadzieję, że pomoże to tym z was, którzy mogą to robić w Pythonie .
Stworzyłem kompletny działający skrypt / rozwiązanie na GitHubGist - zobacz adres URL poniżej tego fragmentu kodu.

# 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))

Zapewnia idempotentne zdalne (RDS) tworzenie roli / użytkownika PostgreSQL z Pythona bez modułów CM itp.

cmcc
źródło
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
źródło