如何在不运行PostgreSQL服务器的情况下初始化PostgreSQL数据库

8
在初始化脚本中,我想初始化一个PostgreSQL目录,但在此阶段不需要(也不希望)运行PostgreSQL服务器。如果我只是创建群集(作为用户postgres),那么这将是一件轻而易举的事情:
initdb -D ...

但是,我还需要创建PostgreSQL角色、创建数据库并添加一些扩展(也必须作为用户postgres):

createuser someuser
createdb -O someuser somedb
echo 'CREATE EXTENSION xyz;' | psql somedb

后面的命令需要运行PostgreSQL服务器。因此,整个过程变得非常混乱:

initdb -D ...

# Start PostgreSQL server in background
... &

# Wait in a loop until PostgreSQL server is up and running
while ! psql -f /dev/null template1; do
    sleep 0.5
done

createuser someuser
createdb -O someuser somedb
echo 'CREATE EXTENSION xyz;' | psql somedb

# Kill PostgreSQL server
kill ...

# Wait until the process is really killed
sleep 2

特别是等待PostgreSQL服务器的部分从来不是100%可靠的。我尝试了很多变体,每个变体大约有1/20的失败率。此外,在简单的shell脚本中杀死该进程可能不是100%可靠的,更不用说确保它已正确停止了。
我相信这是在引导服务器或准备VM映像的所有用例中都会出现的标准问题。因此,人们希望在2016年应该存在某些现有的、可靠的工具。所以我的问题是:
  • 有没有更简单、更可靠的方法实现这一点?
  • 例如,是否有一种运行PostgreSQL服务器的特殊模式,只需启动,执行某些SQL命令,然后在最后一个SQL命令完成后立即退出?
  • 粗略地说,是否有一些内部PostgreSQL测试套件可以重用于此目的?
1个回答

10
你正在寻找单用户模式
如果你以这种方式启动PostgreSQL,你将作为超级用户连接到会话,并等待标准输入中的SQL语句。一旦你断开连接(用文件结束符),服务器进程就会停止。
你可以这样做(使用bash):
postgres --single -D /usr/local/pgsql/data postgres <<-"EOF"
CREATE USER ...;
CREATE DATABASE somedb ...;
EOF

postgres --single -D /usr/local/pgsql/data somedb <<-"EOF"
CREATE EXTENSION ...;
EOF

谢谢!单用户模式是缺失的提示。然而,你的示例代码有点错误。它在数据库创建之前尝试访问数据库。似乎需要执行两次 postgres --single - 一次使用 postgres 数据库,然后再使用已创建的数据库。 - vog
当然。dbname只是一个例子。我会更新答案以提供更多的清晰度。 - Laurenz Albe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接