it-swarm.com.de

Überprüfen Sie mithilfe der Shell, ob eine Datenbank in PostgreSQL vorhanden ist

Ich habe mich gefragt, ob mir jemand sagen könnte, ob es möglich ist, Shell zu verwenden, um zu überprüfen, ob eine PostgreSQL-Datenbank vorhanden ist.

Ich mache ein Shell-Skript und möchte nur, dass die Datenbank erstellt wird, wenn sie noch nicht vorhanden ist, aber bisher noch nicht gesehen hat, wie sie implementiert werden soll.

104
Jimmy

Ich verwende folgende Modifikation der Lösung von Arturo:

psql -lqt | cut -d \| -f 1 | grep -qw <db_name>


Was es macht

psql -l gibt etwas wie das Folgende aus:

                                        List of databases
     Name  |   Owner   | Encoding |  Collate   |   Ctype    |   Access privileges   
-----------+-----------+----------+------------+------------+-----------------------
 my_db     | my_user   | UTF8     | en_US.UTF8 | en_US.UTF8 | 
 postgres  | postgres  | LATIN1   | en_US      | en_US      | 
 template0 | postgres  | LATIN1   | en_US      | en_US      | =c/postgres          +
           |           |          |            |            | postgres=CTc/postgres
 template1 | postgres  | LATIN1   | en_US      | en_US      | =c/postgres          +
           |           |          |            |            | postgres=CTc/postgres
(4 rows)

Die Verwendung des naiven Ansatzes bedeutet, dass die Suche nach einer Datenbank mit dem Namen "Liste", "Zugriff" oder "Zeilen" erfolgreich ist. Daher leiten wir diese Ausgabe durch eine Reihe von integrierten Befehlszeilen-Tools, um nur in der ersten Spalte zu suchen.


Das Flag -t entfernt Kopf- und Fußzeilen:

 my_db     | my_user   | UTF8     | en_US.UTF8 | en_US.UTF8 | 
 postgres  | postgres  | LATIN1   | en_US      | en_US      | 
 template0 | postgres  | LATIN1   | en_US      | en_US      | =c/postgres          +
           |           |          |            |            | postgres=CTc/postgres
 template1 | postgres  | LATIN1   | en_US      | en_US      | =c/postgres          +
           |           |          |            |            | postgres=CTc/postgres

Das nächste Bit, cut -d \| -f 1, teilt die Ausgabe durch das |-Zeichen der vertikalen Pipe (das von der Shell mit einem Backslash entkommen ist) und wählt das Feld 1 aus.

 my_db             
 postgres          
 template0         

 template1         

grep -w stimmt mit ganzen Wörtern überein und stimmt daher nicht überein, wenn Sie in diesem Szenario nach temp suchen. Die Option -q unterdrückt jegliche Ausgabe, die auf den Bildschirm geschrieben wird. Wenn Sie dies interaktiv an einer Eingabeaufforderung ausführen möchten, können Sie den Code -q ausschließen, sodass sofort etwas angezeigt wird.

Beachten Sie, dass grep -w mit alphanumerischen Ziffern und dem Unterstrich übereinstimmt. Dies ist genau die Menge der Zeichen, die in nicht mit Anführungszeichen versehenen Datenbanknamen in postgresql zulässig sind (Bindestriche sind in nicht mit Anführungszeichen versehenen Bezeichnern nicht zulässig). Wenn Sie andere Zeichen verwenden, funktioniert grep -w nicht für Sie.


Der Exit-Status dieser gesamten Pipeline lautet 0 (Erfolg), wenn die Datenbank vorhanden ist, oder 1 (Fehler), falls dies nicht der Fall ist. Ihre Shell setzt die spezielle Variable $? auf den Beendigungsstatus des letzten Befehls. Sie können den Status auch direkt unter Bedingungen testen:

if psql -lqt | cut -d \| -f 1 | grep -qw <db_name>; then
    # database exists
    # $? is 0
else
    # ruh-roh
    # $? is 1
fi
158
kibibu

Der folgende Shell-Code scheint für mich zu funktionieren:

if [ "$( psql -tAc "SELECT 1 FROM pg_database WHERE datname='DB_NAME'" )" = '1' ]
then
    echo "Database already exists"
else
    echo "Database does not exist"
fi
60
Nathan Osman
[email protected]:~$ psql -l | grep <exact_dbname> | wc -l

Dies gibt 1 zurück, wenn die angegebene Datenbank existiert oder 0.

Wenn Sie versuchen, eine bereits vorhandene Datenbank zu erstellen, gibt postgresql eine Fehlermeldung wie die folgende aus:

[email protected]:~$ createdb template1
createdb: database creation failed: ERROR:  database "template1" already exists
24
Arturo

Ich bin neu bei postgresql, aber mit dem folgenden Befehl habe ich überprüft, ob eine Datenbank existiert

if psql ${DB_NAME} -c '\q' 2>&1; then
   echo "database ${DB_NAME} exists"
fi
19
bruce

Ich kombiniere die anderen Antworten zu einer kurzen und POSIX-kompatiblen Form:

psql -lqtA | grep -q "^$DB_NAME|"

Eine Rückgabe von true (0) bedeutet, dass es existiert.

Wenn Sie vermuten, dass Ihr Datenbankname ein nicht standardmäßiges Zeichen wie $ hat, benötigen Sie einen etwas längeren Ansatz:

psql -lqtA | cut -d\| -f1 | grep -qxF "$DB_NAME"

Die Optionen -t und -A stellen sicher, dass es sich bei der Ausgabe um eine unformatierte Ausgabe handelt, die nicht "tabellarisch" oder mit Leerzeichen aufgefüllt ist. Spalten werden durch das Pipe-Zeichen | getrennt, daher muss entweder die cut oder die grep dies erkennen. Die erste Spalte enthält den Datenbanknamen.

EDIT: grep mit -x, um partielle Namensübereinstimmungen zu verhindern.

10
Otheus

Sie können eine Datenbank erstellen, falls noch keine vorhanden ist, indem Sie diese Methode verwenden:

if [[ -z `psql -Atqc '\list mydatabase' postgres` ]]; then createdb mydatabase; fi
7
Nicolas Grilly
#!/bin/sh
DB_NAME=hahahahahahaha
psql -U postgres ${DB_NAME} --command="SELECT version();" >/dev/null 2>&1
RESULT=$?
echo DATABASE=${DB_NAME} RESULT=${RESULT}
#
5
wildplasser

Der Vollständigkeit halber wird eine andere Version verwendet, die Regex verwendet, anstatt das Schneiden von Strings:

psql -l | grep '^ exact_dbname\b'

So zum Beispiel:

if psql -l | grep '^ mydatabase\b' > /dev/null ; then
  echo "Database exists already."
  exit
fi
3
Steve Bennett

kibibus akzeptierte Antwort ist fehlerhaft, weil grep -w mit dem Namen any übereinstimmt, der das angegebene Muster als Word-Komponente enthält.

wenn Sie nach "foo" suchen, ist "foo-backup" eine Übereinstimmung.

Die Antwort von Otheus bietet einige gute Verbesserungen, und die kurze Version wird in den meisten Fällen korrekt funktionieren, aber die längere der beiden angebotenen Varianten weist ein ähnliches Problem mit übereinstimmenden Teilzeichenfolgen auf.

Um dieses Problem zu beheben, können wir das POSIX-Argument -x verwenden, um nur ganze Zeilen des Textes abzugleichen.

Aufbauend auf Otheus 'Antwort sieht die neue Version folgendermaßen aus:

psql -U "$USER" -lqtA | cut -d\| -f1 | grep -qFx "$DBNAME"

Alles in allem bin ich geneigt zu sagen, dass Nicolas Grillys Antwort - wo Sie Postgres tatsächlich nach der spezifischen Datenbank fragen - der beste Ansatz von allen ist.

2
phils

Die anderen (fantastischen) Lösungen vermissen die Tatsache, dass psql eine Minute oder länger warten kann, bevor das Zeitlimit überschritten wird, wenn keine Verbindung zu einem Host hergestellt werden kann. Also, ich mag diese Lösung, die das Timeout auf 3 Sekunden setzt:

PGCONNECT_TIMEOUT=3 psql development -h db -U postgres -c ""

Dies ist für die Verbindung mit einer Entwicklungsdatenbank auf dem offiziellen postgres Alpine Docker-Image.

Wenn Sie Rails verwenden und eine Datenbank einrichten möchten, die noch nicht vorhanden ist (wie beim Starten eines Docker-Containers), funktioniert dies gut, da Migrationen idempotent sind:

bundle exec rake db:migrate 2>/dev/null || bundle exec rake db:setup
0
dankohn

Ich bin noch ziemlich unerfahren mit der Shell-Programmierung. Wenn das aus irgendeinem Grund wirklich falsch ist, dann weise mich ab, aber sei nicht zu besorgt.

Aufbauend auf Kibibus Antwort:

# If resulting string is not zero-length (not empty) then...
if [[ ! -z `psql -lqt | cut -d \| -f 1 | grep -w $DB_NAME` ]]; then
  echo "Database $DB_NAME exists."
else
  echo "No existing databases are named $DB_NAME."
fi
0
David Winiecki

psql -l|awk '{print $1}'|grep -w <database>

kürzere Version

0
Justin