Проверьте, существует ли база данных в PostgreSQL с помощью shell
Мне было интересно, сможет ли кто-нибудь рассказать мне о том, можно ли использовать shell для проверки наличия базы данных PostgreSQL?
Я делаю сценарий оболочки, и я только хочу, чтобы он создал базу данных, если она еще не существует, но до сих пор не смогла увидеть, как ее реализовать.
12 ответов
я использую следующую модификацию решения Артуро:
psql -lqt | cut -d \| -f 1 | grep -qw <db_name>
что это значит
psql -l
выводит что-то вроде следующего:
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)
использование наивного подхода означает, что поиск базы данных под названием "Список"," доступ "или" строки " будет успешным. Поэтому мы передаем этот вывод через кучу встроенных инструментов командной строки только для поиска в первом столбце.
на -t
флаг удаление колонтитулов:
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
затем cut -d \| -f 1
разделяет выход по вертикальной трубе |
символ (экранированный из оболочки с обратной косой чертой) и выбирает поле 1. Это оставляет:
my_db
postgres
template0
template1
grep -w
соответствует целым словам, и поэтому не будет соответствовать, если вы ищете temp
в этом случае. The -q
опция подавляет любые выходные данные, записанные на экран, поэтому, если вы хотите запустить это интерактивно в командной строке, вы может с исключить -q
таким образом, что-то отображается немедленно.
отметим, что grep -w
соответствует буквенно-цифровым, цифрам и подчеркиванию, которое является точно набором символов, разрешенных в именах баз данных без кавычек в postgresql (дефисы не являются законными в идентификаторах без кавычек). Если вы используете другие символы, grep -w
не будет работать для вас.
статус выхода всего этого трубопровода будет 0
(успех) если база данных существует или 1
(неудача) если это не так. Ваша оболочка установит специальную переменную $?
статус выхода последней команды. Вы также можете проверить статус непосредственно в условном:
if psql -lqt | cut -d \| -f 1 | grep -qw <db_name>; then
# database exists
# $? is 0
else
# ruh-roh
# $? is 1
fi
следующий код оболочки, кажется, работает для меня:
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
возвращает 1, если указанная база данных существует, или 0 в противном случае.
кроме того, если вы попытаетесь создать базу данных, которая уже существует, postgresql вернет сообщение об ошибке следующим образом:
postgres@desktop:~$ createdb template1
createdb: database creation failed: ERROR: database "template1" already exists
Я новичок в postgresql, но следующая команда-это то, что я использовал, чтобы проверить, существует ли база данных
if psql ${DB_NAME} -c '\q' 2>&1; then
echo "database ${DB_NAME} exists"
fi
я объединяю другие ответы в краткую и совместимую с POSIX форму:
psql -lqtA | grep -q "^$DB_NAME|"
возвращение true
(0
) означает, что он существует.
если вы подозреваете, что имя вашей базы данных может иметь нестандартный символ, такой как $
, вам нужен немного более длинный подход:
psql -lqtA | cut -d\| -f1 | grep -qxF "$DB_NAME"
на -t
и -A
параметры убедитесь, что вывод является необработанным, а не "табличным" или заполненным пробелами. Столбцы разделяются символом трубы |
, так что либо cut
или grep
должен признать это. Первый столбец содержит имя базы данных.
EDIT: grep с -x, чтобы предотвратить частичные совпадения имен.
#!/bin/sh
DB_NAME=hahahahahahaha
psql -U postgres ${DB_NAME} --command="SELECT version();" >/dev/null 2>&1
RESULT=$?
echo DATABASE=${DB_NAME} RESULT=${RESULT}
#
вы можете создать базу данных, если она уже не существует, используя этот метод:
if [[ -z `psql -Atqc '\list mydatabase' postgres` ]]; then createdb mydatabase; fi
для полноты другая версия, использующая регулярное выражение, а не резку строк:
psql -l | grep '^ exact_dbname\b'
например:
if psql -l | grep '^ mydatabase\b' > /dev/null ; then
echo "Database exists already."
exit
fi
kibibu это принято отвечать имеет недостатки в этом grep -w
будет соответствовать любой имя, содержащее указанный шаблон в качестве компонента word.
т. е. если вы ищете "foo", то" foo-backup " соответствует.
Otheus это обеспечивает некоторые хорошие улучшения, и короткая версия будет работать правильно в большинстве случаев, но более длинный из двух предложенных вариантов демонстрирует аналогичную проблему с соответствующими подстроками.
В решить эту проблему, мы можем использовать POSIX -x
аргумент для соответствия только весь строки текста.
основываясь на ответе Отеуса, новая версия выглядит так:
psql -U "$USER" -lqtA | cut -d\| -f1 | grep -qFx "$DBNAME"
этим все сказано, я склонен сказать, что ответ Николя Грилли -- где вы на самом деле спрашиваете postgres о конкретной базе данных-это лучший подход из всех.
Я все еще довольно неопытен в программировании оболочки, поэтому, если это действительно неправильно по какой-то причине, проголосуйте за меня, но не слишком тревожьтесь.
здание из ответа кибибу:
# 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 может подождать минуту или больше до тайм-аута, если он не может подключиться к хосту. Итак, мне нравится это решение, которое задает таймаут в 3 секунды:
PGCONNECT_TIMEOUT=3 psql development -h db -U postgres -c ""
Это для подключения к базе данных разработки на официальном postgres изображение Alpine Docker.
отдельно, если вы используете Rails и хотите настроить базу данных, если она еще не существует (как при запуске Докера container), это хорошо работает, так как миграции идемпотентны:
bundle exec rake db:migrate 2>/dev/null || bundle exec rake db:setup