createuser
允许在 PostgreSQL 中创建用户 (ROLE)。有没有一种简单的方法来检查该用户(名称)是否已经存在?否则 createuser 返回错误:
createuser: creation of new role failed: ERROR: role "USR_NAME" already exists
更新:该解决方案最好可以从 shell 执行,这样更容易在脚本内实现自动化。
SELECT 1 FROM pg_roles WHERE rolname='USR_NAME'
在命令行方面(感谢 Erwin):
psql postgres -tXAc "SELECT 1 FROM pg_roles WHERE rolname='USR_NAME'"
如果找到,则产量 1,没有其他。
即:
psql postgres -tXAc "SELECT 1 FROM pg_roles WHERE rolname='USR_NAME'" | grep -q 1 || createuser ...
遵循相同的想法检查数据库是否存在
psql -t -c '\du' | cut -d \| -f 1 | grep -qw <user_to_check>
您可以在这样的脚本中使用它:
if psql -t -c '\du' | cut -d \| -f 1 | grep -qw <user_to_check>; then
# user exists
# $? is 0
else
# ruh-roh
# $? is 1
fi
psql -qtA -c "\du USR_NAME" | cut -d "|" -f 1
[[ -n $(psql -qtA -c "\du ${1}" | cut -d "|" -f 1) ]] && echo "exists" || echo "does not exist"
希望这对那些可能在 python 中这样做的人有所帮助。
我在 GitHubGist 上创建了一个完整的工作脚本/解决方案 - 请参阅此代码片段下面的 URL。
# ref: https://stackoverflow.com/questions/8546759/how-to-check-if-a-postgres-user-exists
check_user_cmd = ("SELECT 1 FROM pg_roles WHERE rolname='%s'" % (deis_app_user))
# our create role/user command and vars
create_user_cmd = ("CREATE ROLE %s WITH LOGIN CREATEDB PASSWORD '%s'" % (deis_app_user, deis_app_passwd))
# ref: https://stackoverflow.com/questions/37488175/simplify-database-psycopg2-usage-by-creating-a-module
class RdsCreds():
def __init__(self):
self.conn = psycopg2.connect("dbname=%s user=%s host=%s password=%s" % (admin_db_name, admin_db_user, db_host, admin_db_pass))
self.conn.set_isolation_level(0)
self.cur = self.conn.cursor()
def query(self, query):
self.cur.execute(query)
return self.cur.rowcount > 0
def close(self):
self.cur.close()
self.conn.close()
db = RdsCreds()
user_exists = db.query(check_user_cmd)
# PostgreSQL currently has no 'create role if not exists'
# So, we only want to create the role/user if not exists
if (user_exists) is True:
print("%s user_exists: %s" % (deis_app_user, user_exists))
print("Idempotent: No credential modifications required. Exiting...")
db.close()
else:
print("%s user_exists: %s" % (deis_app_user, user_exists))
print("Creating %s user now" % (deis_app_user))
db.query(create_user_cmd)
user_exists = db.query(check_user_cmd)
db.close()
print("%s user_exists: %s" % (deis_app_user, user_exists))
要完全在单个 psql 命令中完成此操作:
DO $$BEGIN
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = 'USR_NAME')
THEN CREATE ROLE USR_NAME;
END IF;
END$$;
受到接受的答案的启发,不幸的是这对我不起作用(直接
psql
调用时出错),然后我做了这样的事情:
if ! echo "SELECT * FROM pg_roles WHERE rolname='USR_NAME'" | psql -h localhost -U postgres | grep -E "[1-9][0-9]* rows"; then
# User not found, create it
if ! echo "CREATE USER USR_NAME WITH PASSWORD 'USR_NAME' CREATEDB SUPERUSER" | psql -h localhost -U postgres; then
echo "Error creating USR_NAME"
exit 1
fi
fi
即使我认为
grep -E "1 rows"
在这里是安全的,因为我们不应该有超过一个同名用户,但我更喜欢保留 grep -E "[1-9][0-9]* rows"
以获得通用的“我得到 1 个或更多结果”返回成功。
如果失败,我会添加 exit 1
,因为我所在的脚本需要创建此用户才能正常运行。