Je me demandais si quelqu'un pourrait me dire s'il est possible d'utiliser Shell pour vérifier si une base de données PostgreSQL existe?
Je suis en train de créer un script Shell et je ne veux que celle-ci crée la base de données si elle n'existe pas déjà, mais jusqu'à présent, je ne savais pas comment la mettre en œuvre.
J'utilise la modification suivante de la solution d'Arturo:
psql -lqt | cut -d \| -f 1 | grep -qw <db_name>
psql -l
génère quelque chose comme ceci:
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)
L'utilisation de l'approche naïve signifie que la recherche d'une base de données appelée "Liste," Accès "ou" lignes "réussira. Nous dirigeons donc cette sortie vers un ensemble d'outils de ligne de commande intégrés pour rechercher uniquement dans la première colonne.
Le drapeau -t
supprime les en-têtes et les pieds de page:
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
Le bit suivant, cut -d \| -f 1
divise la sortie par le caractère |
de tuyau vertical (échappé du shell avec une barre oblique inversée) et sélectionne le champ 1. Cela laisse:
my_db
postgres
template0
template1
grep -w
correspond aux mots entiers, et donc ne correspondra pas si vous recherchez temp
dans ce scénario. L'option -q
supprime toute sortie écrite à l'écran. Par conséquent, si vous souhaitez l'exécuter de manière interactive à l'invite d'une commande, vous pouvez exclure le -q
afin que quelque chose soit affiché immédiatement.
Notez que grep -w
correspond aux caractères alphanumériques, aux chiffres et au trait de soulignement, qui correspond exactement au jeu de caractères autorisé dans les noms de base de données non cités dans postgresql (les traits d'union ne sont pas légaux dans les identificateurs non cités). Si vous utilisez d'autres caractères, grep -w
ne fonctionnera pas pour vous.
Le statut de sortie de l'ensemble du pipeline sera 0
(succès) si la base de données existe ou 1
(échec) s'il ne l'est pas. Votre shell définira la variable spéciale $?
sur le statut de sortie de la dernière commande. Vous pouvez également tester le statut directement dans une condition:
if psql -lqt | cut -d \| -f 1 | grep -qw <db_name>; then
# database exists
# $? is 0
else
# ruh-roh
# $? is 1
fi
Le code Shell suivant semble fonctionner pour moi:
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
postgres@desktop:~$ psql -l | grep <exact_dbname> | wc -l
Cela renverra 1 si la base de données spécifiée existe ou 0 sinon.
De plus, si vous essayez de créer une base de données qui existe déjà, postgresql renverra un message d'erreur du type
postgres@desktop:~$ createdb template1
createdb: database creation failed: ERROR: database "template1" already exists
Postgresql est nouveau pour moi, mais la commande suivante m'a permis de vérifier l'existence d'une base de données.
if psql ${DB_NAME} -c '\q' 2>&1; then
echo "database ${DB_NAME} exists"
fi
Je combine les autres réponses à un formulaire succinct et compatible POSIX:
psql -lqtA | grep -q "^$DB_NAME|"
Un retour de true
(0
) signifie qu'il existe.
Si vous pensez que le nom de votre base de données pourrait avoir un caractère non standard tel que $
, vous avez besoin d'une approche légèrement plus longue:
psql -lqtA | cut -d\| -f1 | grep -qxF "$DB_NAME"
Les options -t
et -A
permettent de s'assurer que la sortie est brute et non "tabulaire" ou complétée par des espaces. Les colonnes sont séparées par le caractère de pipe |
. Par conséquent, la variable cut
ou la variable grep
doit le reconnaître. La première colonne contient le nom de la base de données.
EDIT: grep avec -x pour éviter les correspondances partielles de noms.
Vous pouvez créer une base de données, si elle n'existe pas déjà, en utilisant cette méthode:
if [[ -z `psql -Atqc '\list mydatabase' postgres` ]]; then createdb mydatabase; fi
#!/bin/sh
DB_NAME=hahahahahahaha
psql -U postgres ${DB_NAME} --command="SELECT version();" >/dev/null 2>&1
RESULT=$?
echo DATABASE=${DB_NAME} RESULT=${RESULT}
#
Pour être complet, utilisez une autre version utilisant regex plutôt que la coupe de chaînes:
psql -l | grep '^ exact_dbname\b'
Donc par exemple:
if psql -l | grep '^ mydatabase\b' > /dev/null ; then
echo "Database exists already."
exit
fi
réponse acceptée de kibibu est défectueux car grep -w
correspondra à tout nom contenant le modèle spécifié en tant que composant Word.
si vous recherchez "foo", alors "foo-backup" est une correspondance.
La réponse d'Otheus apporte de bonnes améliorations, et la version courte fonctionnera correctement dans la plupart des cas, mais la plus longue des deux variantes proposées présente un problème similaire avec les sous-chaînes correspondantes.
Pour résoudre ce problème, nous pouvons utiliser l'argument POSIX -x
pour ne faire correspondre que les lignes entières du texte.
S'appuyant sur la réponse d'Otheus, la nouvelle version ressemble à ceci:
psql -U "$USER" -lqtA | cut -d\| -f1 | grep -qFx "$DBNAME"
Cela étant dit, je suis enclin à dire que la réponse de Nicolas Grilly - où vous posez des questions à Postgres au sujet de la base de données spécifique - est la meilleure approche.
Les autres solutions (qui sont fantastiques) oublient le fait que psql peut attendre une minute ou plus avant de s’expulser s’il ne parvient pas à se connecter à un hôte. Donc, j'aime bien cette solution, qui fixe le délai d'attente à 3 secondes:
PGCONNECT_TIMEOUT=3 psql development -h db -U postgres -c ""
Ceci est destiné à la connexion à une base de données de développement sur l'image officielle postgres Alpine Docker.
Séparément, si vous utilisez Rails et souhaitez configurer une base de données si elle n’existe pas déjà (comme lors du lancement d’un conteneur Docker), cela fonctionne bien, car les migrations sont idempotentes:
bundle exec rake db:migrate 2>/dev/null || bundle exec rake db:setup
Je ne connais pas encore très bien la programmation Shell. Si cela ne vous convient pas pour une raison quelconque, votez pour moi, mais ne vous inquiétez pas trop.
Construire à partir de la réponse de kibibu:
# 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
psql -l|awk '{print $1}'|grep -w <database>
version plus courte