Compruebe si la base de datos existe en PostgreSQL usando shell


Me preguntaba si alguien podría decirme si es posible usar shell para verificar si existe una base de datos PostgreSQL.

Estoy haciendo un script de shell y solo quiero que cree la base de datos si aún no existe pero hasta ahora no he podido ver cómo implementarla.

Author: wonea, 2013-01-27

12 answers

Utilizo la siguiente modificación de la solución de Arturo:{[19]]}

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


Lo que hace

psql -l salidas algo como lo siguiente:

                                        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)

Usar el enfoque ingenuo significa que la búsqueda de una base de datos llamada "List, "Access" o "rows" tendrá éxito. Así que canalizamos esta salida a través de un montón de herramientas de línea de comandos integradas para buscar solo en la primera columna.


La bandera -t elimina los encabezados y pie de página:

 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

El siguiente bit, cut -d \| -f 1 divide la salida por el carácter vertical pipe | (escapado del shell con una barra invertida), y selecciona el campo 1. Esto deja:

 my_db             
 postgres          
 template0         

 template1         

grep -w coincide con palabras enteras, por lo que no coincidirá si está buscando temp en este escenario. La opción -q suprime cualquier salida escrita en la pantalla, por lo que si desea ejecutar esto interactivamente en un símbolo del sistema, puede excluir -q para que se muestre algo inmediatamente.

Tenga en cuenta que grep -w coincide con caracteres alfanuméricos, dígitos y el subrayado, que es exactamente el conjunto de caracteres permitidos en los nombres de bases de datos sin comillas en postgresql (los guiones no son legales en los identificadores sin comillas). Si está utilizando otros caracteres, grep -w no funcionará para usted.


El estado de salida de toda esta canalización será 0 (éxito) si la base de datos existe o 1 (error) si no lo hace. Su shell establecerá la variable especial $? en el estado de salida de la última orden. También puede probar el estado directamente en un condicional:

if psql -lqt | cut -d \| -f 1 | grep -qw <db_name>; then
    # database exists
    # $? is 0
else
    # ruh-roh
    # $? is 1
fi
 150
Author: kibibu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-19 07:05:21

El siguiente código de shell parece funcionar para mí:

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
 51
Author: Nathan Osman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-21 14:01:45
postgres@desktop:~$ psql -l | grep <exact_dbname> | wc -l

Esto devolverá 1 si la base de datos especificada existe o 0 de lo contrario.

Además, si intenta crear una base de datos que ya existe, postgresql devolverá un mensaje de error como este:

postgres@desktop:~$ createdb template1
createdb: database creation failed: ERROR:  database "template1" already exists
 23
Author: Arturo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-27 11:19:08

Soy nuevo en postgresql, pero el siguiente comando es lo que usé para comprobar si existe una base de datos

if psql ${DB_NAME} -c '\q' 2>&1; then
   echo "database ${DB_NAME} exists"
fi
 18
Author: bruce,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-21 02:05:19

Estoy combinando las otras respuestas a una forma sucinta y compatible con POSIX:

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

Un retorno de true (0) significa que existe.

Si sospecha que el nombre de su base de datos puede tener un carácter no estándar como $, necesita un enfoque un poco más largo:

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

Las opciones -t y -A se aseguran de que la salida sea raw y no "tabular" o rellena con espacios en blanco. Las columnas están separadas por el carácter de tubería |, por lo que el cut o el grep tiene que reconoce esto. La primera columna contiene el nombre de la base de datos.

EDIT: grep con-x para evitar coincidencias parciales de nombres.

 10
Author: Otheus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-24 15:58:47
#!/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
Author: wildplasser,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-27 16:18:14

Puede crear una base de datos, si aún no existe, utilizando este método:

if [[ -z `psql -Atqc '\list mydatabase' postgres` ]]; then createdb mydatabase; fi
 5
Author: Nicolas Grilly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-09 09:12:30

Para completar, otra versión que usa expresiones regulares en lugar de cortar cadenas:

psql -l | grep '^ exact_dbname\b'

Por ejemplo:

if psql -l | grep '^ mydatabase\b' > /dev/null ; then
  echo "Database exists already."
  exit
fi
 3
Author: Steve Bennett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-13 12:18:45

La respuesta aceptada de Kibibu es defectuosa en que grep -w coincidirá con cualquier nombre que contenga el patrón especificado como un componente de palabra.

Es decir, si buscas "foo", entonces "foo-backup" es una coincidencia.

La respuesta de Otheus proporciona algunas buenas mejoras, y la versión corta funcionará correctamente para la mayoría de los casos, pero la más larga de las dos variantes ofrece un problema similar con subcadenas coincidentes.

Para resolver este problema, podemos usar el POSIX -xargumento para coincidir solo con líneas completas del texto.

Basándose en la respuesta de Oteo, la nueva versión se ve así:

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

Dicho todo, me inclino a decir que La respuesta de Nicolas Grilly where donde realmente le preguntas a postgres sobre la base de datos específica is es el mejor enfoque de todos.

 2
Author: phils,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:29

Todavía soy bastante inexperto con la programación de shell, así que si esto es realmente malo por alguna razón, votarme, pero no te alarmes demasiado.

Construyendo a partir de la respuesta 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
 0
Author: David Winiecki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-16 09:30:12

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

Versión abreviada

 0
Author: Justin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-08 10:23:30

Las otras soluciones (que son fantásticas) pierden el hecho de que psql puede esperar un minuto o más antes de agotarse si no puede conectarse a un host. Por lo tanto, me gusta esta solución, que establece el tiempo de espera a 3 segundos:

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

Esto es para conectarse a una base de datos de desarrollo en la imagen oficial postgres Alpine Docker.

Por separado, si está utilizando Rails y desea configurar una base de datos si aún no existe (como al lanzar un contenedor Docker), esto funciona bien, ya que las migraciones son idempotentes:

bundle exec rake db:migrate 2>/dev/null || bundle exec rake db:setup
 0
Author: dankohn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-27 05:10:53