Bash PostgreSQL数据库如何在两个连续的shell命令之间停止存在?
我试图在CI中创建PostgreSQL数据库Bash PostgreSQL数据库如何在两个连续的shell命令之间停止存在?,bash,postgresql,psql,gitlab-ci,postgres-9.6,Bash,Postgresql,Psql,Gitlab Ci,Postgres 9.6,我试图在CI中创建PostgreSQL数据库accounts\u db(GitLab CI,如果相关的话),但前提是该数据库还不存在。由于本机Postgres不支持这一点,我目前通过使用psql在pg_数据库上运行SELECT来解决这个问题,并且只有当它不返回结果时,我才再次使用psql运行CREATE database: psql -tc "SELECT 1 FROM pg_database WHERE datname = 'accounts_db';" | grep -q 1 || psql
accounts\u db
(GitLab CI,如果相关的话),但前提是该数据库还不存在。由于本机Postgres不支持这一点,我目前通过使用psql在pg_数据库上运行SELECT
来解决这个问题,并且只有当它不返回结果时,我才再次使用psql运行CREATE database
:
psql -tc "SELECT 1 FROM pg_database WHERE datname = 'accounts_db';" | grep -q 1 || psql -c "CREATE DATABASE accounts_db;"
这在大多数情况下都有效:accounts\u db
已经存在,因此grep
成功退出,而CREATE DATABASE
未执行
不过,大部分时间并不是所有时间。出于某种原因,它有时会出现在| |
的第二部分,但由于数据库已经存在而出错:
$ psql -tc "SELECT 1 FROM pg_database WHERE datname = 'accounts_db';" | grep -q 1 || psql -c "CREATE DATABASE accounts_db;"
ERROR: database "accounts_db" already exists
这怎么可能呢?顺便说一句:你不需要grep;您可以使用psql的退出代码,只需尝试连接到新数据库:
(psql以非零退出值退出有更多原因;但在这种情况下,第二个psql也将失败)
但更简单的是:只要尝试创建数据库,如果失败,就退出脚本:
您是否有可能混淆了真实的db名称,而真实的db名称有时包含大小写混合
因为
SELECT 1 FROM pg_database WHERE datname = 'MyDB'
将匹配名为MyDB
的数据库,但不匹配名为MyDB
的数据库。但是,如果您创建数据库,您将获得一个案例名称;e、 g
CREATE DATABASE MyDB;
创建名为mydb
的数据库。因此在这种情况下,您的生存测试将报告没有名为MyDB
的数据库,然后您将去创建它,尝试创建MyDB
,如果它已经存在,则失败
修复方法是使用标识符引用:
CREATE DATABASE "MyDB";
在那里保留案例。或者,将pg_数据库的查询大小写折叠为小写:
SELECT 1 FROM pg_database WHERE datname = lower('MyDB')
。。。假设您知道您只会尝试用小写字母创建它
(如果用户决定向脚本提供带标识符的输入,则更令人兴奋…注意:您的命令不包含要连接的数据库名。你有一个以你的用户名为名称的数据库吗?在没有grep的情况下运行第一位,看看它输出了什么。还有,如果postgres不支持它,只需运行第二个命令……它将根据您的环境输出行号。搜索字符串“1”时,该字符串不一定是select语句返回的值1。使用check database select语句的输出更新您的问题(当问题存在或不存在时)。它们都可能包含一个“1”。从pg_数据库中选择“magic_string”,其中…;|grep-q magic_string…
@wildplasser,设置为环境变量。请注意,它在大多数情况下都能工作。实际上,如果数据库已经存在,我希望它能够成功,但如果在创建数据库时出现其他错误,则不希望它成功。但是您的第一个选项听起来不错,让met试试。您可以在shell脚本中捕获结果代码result=$?
,并根据其值执行操作。好吧,现在看来这是可行的。遗憾的是,我不知道实际的问题是什么,但我会密切关注这一点,并接受这个答案,如果它看起来不再失败的话。无论如何,感谢您的帮助:)经过七次重试,七次都成功了,现在看起来已经足够稳定了。我猜这与grep、管道或其他Bash相关的东西有关,我对Bash没有足够的经验来理解。不管怎样,它现在可以工作了,谢谢@Vincent Race条件下,多个并发脚本尝试执行相同的操作,那么可能吗?我可以看到只有一个CI作业正在执行,它只是运行我在问题中发布的命令。它似乎也不再发生后删除grep。。。
CREATE DATABASE "MyDB";
SELECT 1 FROM pg_database WHERE datname = lower('MyDB')