シェルを使用してPostgreSQLデータベースが存在するかどうかを確認できるかどうかを誰かが教えてくれるかどうか疑問に思っていました。
私はシェルスクリプトを作成していますが、データベースがまだ存在していない場合にのみデータベースを作成したいのですが、今まではそれを実装する方法がわかりませんでした。
Arturoのソリューションの次の変更を使用します。
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)
単純なアプローチを使用すると、「List」、「Access」、または「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
を検索している場合は一致しません。 -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
のいずれかがこれを認識する必要があります。最初の列にはデータベース名が含まれています。
編集:部分的な名前の一致を防ぐために-xを指定したgrep。
このメソッドを使用して、データベースがまだ存在しない場合は作成できます。
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}
#
完全を期すために、文字列の切断ではなく正規表現を使用する別のバージョン:
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コンポーネントとして指定されたパターンを含む名前anyと一致するという点で欠陥があります。
つまり、「foo」を検索すると、「foo-backup」が一致します。
オテウスの答え はいくつかの良い改善を提供し、短いバージョンはほとんどの場合正しく動作しますが、提供される2つのバリアントのうち長い方は、部分文字列のマッチングで同様の問題を示します。
この問題を解決するには、POSIX -x
引数を使用して、テキストのentire行のみに一致させることができます。
Otheusの答えに基づいて、新しいバージョンは次のようになります。
psql -U "$USER" -lqtA | cut -d\| -f1 | grep -qFx "$DBNAME"
とはいえ、私は Nicolas Grillyの答え -特定のデータベースについてpostgresに実際に尋ねる-がすべての最良のアプローチであると言いたいと思います。
psql -l|awk '{print $1}'|grep -w <database>
短いバージョン
他のソリューション(素晴らしい)は、psqlがホストに接続できない場合にタイムアウトになるまで1分以上待つことができるという事実を見逃しています。したがって、タイムアウトを3秒に設定するこのソリューションが気に入っています。
PGCONNECT_TIMEOUT=3 psql development -h db -U postgres -c ""
これは、公式の postgres Alpine Dockerイメージ上の開発データベースに接続するためのものです。
それとは別に、Railsを使用していて、データベースがまだ存在しない場合(Dockerコンテナーを起動するときなど)にセットアップしたい場合、移行はべき等であるため、これはうまく機能します。
bundle exec rake db:migrate 2>/dev/null || bundle exec rake db:setup
シェルプログラミングにはまだ慣れていないので、何らかの理由でこれが本当に間違っている場合は、私に投票してください。しかし、心配しないでください。
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