mysql中管理数据库用户的脚本与自动化工具

来源:这里教程网 时间:2026-02-28 20:49:38 作者:

如何用 shell 脚本批量创建 MySQL 用户并授权

直接写脚本比进

mysql
客户端一条条输快得多,但要注意权限语句必须用单引号包裹,避免 shell 解析特殊字符。常见错误是把
GRANT
里的数据库名写成变量却没加反引号,导致库名含短横线(如
my-app
)时语法报错。

实操建议:

mysql -u root -p<password></password>
连接,密码不交互式输入时务必确保脚本权限为
600
,防止泄露
用户主机名别硬写
'%'
,生产环境优先用具体 IP 段或内网域名,如
'10.20.%.%'
授权后必须显式执行
FLUSH PRIVILEGES;
,否则新用户无法登录(MySQL 8.0+ 在部分场景下可省略,但兼容性起见仍建议保留)
#!/bin/bash
USER="app_user"
PASS="s3cur3_p@ss"
DB="myapp_prod"
<p>mysql -u root -p'your_root_pass' -e "
CREATE USER IF NOT EXISTS '$USER'@'10.20.%.%' IDENTIFIED BY '$PASS';
GRANT SELECT, INSERT, UPDATE ON `$DB`.* TO '$USER'@'10.20.%.%';
FLUSH PRIVILEGES;"

Python 脚本自动同步用户配置到多台 MySQL 实例

当有主从、分片或测试/预发多套环境时,靠人工逐台同步用户极易漏配或权限不一致。用 Python 的

pymysql
mysql-connector-python
可读取 YAML 配置文件,再并发连接各实例执行相同 SQL。

关键点:

不要在循环里反复调用
subprocess.run(['mysql', ...])
,开销大且难统一处理错误;改用数据库驱动原生连接
用户密码需加密存储,至少用环境变量传入,避免明文写在 YAML 里 MySQL 8.0 默认认证插件是
caching_sha2_password
,旧版驱动可能连不上,需在连接参数中指定
auth_plugin='mysql_native_password'
import yaml
import pymysql
<p>with open("users.yaml") as f:
config = yaml.safe_load(f)</p><p>for host in config["targets"]:
try:
conn = pymysql.connect(
host=host,
user="root",
password=config["root_pass"],
auth_plugin="mysql_native_password"
)
with conn.cursor() as cur:
cur.execute("CREATE USER IF NOT EXISTS 'reporter'@'%' IDENTIFIED BY %s", (config["reporter_pass"],))
cur.execute("GRANT SELECT ON <em>.</em> TO 'reporter'@'%'")
conn.commit()
except Exception as e:
print(f"Failed on {host}: {e}")
finally:
conn.close()

为什么 mysql.user 表不能直接 INSERT,而要用 CREATE USER

直接往

mysql.user
表 INSERT 是危险操作:MySQL 8.0+ 的密码哈希格式、插件字段(
plugin
)、过期策略(
password_expired
)等字段逻辑复杂,手写容易出错。更严重的是,某些字段(如
account_locked
)在老版本不存在,INSERT 会因列数不匹配失败。

正确做法只有两个:

始终用
CREATE USER
+
GRANT
组合,这是唯一受支持的接口
若真要批量导入,先用
mysqldump --no-create-info mysql user
导出结构,再对照生成合规 INSERT,但仅限离线调试,禁止上线使用

用 pt-show-grants 生成可审计的用户权限快照

pt-show-grants
(Percona Toolkit 中的工具)能将当前所有用户的权限导出为标准
CREATE USER
GRANT
语句,格式清晰、可 diff、可存 Git 版本控制,比人工查
SHOW GRANTS FOR 'u'@'h'
高效太多。

使用注意:

它默认只输出非匿名用户,如需包含
''@'localhost'
,得加
--all
参数
输出不含
FLUSH PRIVILEGES
,回放脚本时要自己补上
MySQL 8.0 的角色(ROLE)权限会被正确还原,但要求 Percona Toolkit ≥ 3.3.0
$ pt-show-grants --user=root --password=xxx > grants-20240520.sql
$ grep "app_user" grants-20240520.sql
CREATE USER 'app_user'@'10.20.%.%' IDENTIFIED WITH 'caching_sha2_password' AS '$A$...';
GRANT SELECT, INSERT, UPDATE ON `myapp_prod`.* TO 'app_user'@'10.20.%.%';

MySQL 用户管理真正的难点不在语法,而在权限最小化落地、多环境一致性校验、以及密码生命周期管理——这些没法靠一个

CREATE USER
语句解决,得靠脚本约束流程,再靠定期审计兜底。

相关推荐