背景
CleanLearn 的 MariaDB 数据库有一个应用用户 english_app,原始密码是 english_app_pass——太弱了,而且是明文写在多个配置文件里的。出于安全考虑,决定把密码换掉,同时把忘了的 root 密码也重置。
看起来很简单:改 config.py → 改 MySQL 用户密码 → 重启服务。实际上踩了一串坑。
踩坑全记录
坑 1:改了配置文件但忘了改数据库
第一步很自然地用 sed 把 /opt/english-api/config.py 里的 english_app_pass 替换成了 mypwd。改完重启服务——所有 API 返回 500。
原因很简单:MySQL 里 english_app 用户的密码还是旧的。配置文件改了,但数据库用户密码没同步,连接当然失败。
坑 2:不知道 root 密码
要改 english_app 的密码,需要 root 权限。但 root 密码是什么?翻遍了服务器上的配置文件、脚本、环境变量,都没有。尝试无密码登录:
mysql -u root # 不行
mysql -u root -p # 不知道密码
mariadb -u root # 也不行
MariaDB 10.11 默认没有开启 unix_socket 认证,root 必须用密码。唯一的办法:跳过权限验证启动。
坑 3:skip-grant-tables 下的 ALTER USER 不生效
跳过权限验证的标准操作:
systemctl stop mariadb
mariadbd --skip-grant-tables --user=mysql &
mariadb -u root -e "ALTER USER 'english_app'@'localhost' IDENTIFIED BY 'mypwd';"
结果报错:
ERROR 1290 (HY000): The MariaDB server is running with the
--skip-grant-tables option so it cannot execute this statement
在 --skip-grant-tables 模式下,权限表完全不加载,所以 ALTER USER 这类 DCL 语句不能直接执行。必须先 FLUSH PRIVILEGES 加载权限表,再执行 ALTER:
mariadb -u root -e "
FLUSH PRIVILEGES;
ALTER USER 'english_app'@'localhost' IDENTIFIED BY 'mypwd';
ALTER USER 'root'@'localhost' IDENTIFIED BY 'mypwd';
FLUSH PRIVILEGES;
"
坑 4:临时进程没杀掉,服务起不来
密码改完后,用 kill %1 杀临时 mariadbd 进程,然后 systemctl start mariadb。结果服务启动失败——因为临时进程是 nohup 启动的,kill %1 在非交互式 SSH 中无效,旧进程还占着 3306 端口。
正确做法是 pkill -9 mariadbd 彻底清场再重启:
pkill -9 mariadbd
sleep 2
systemctl start mariadb
# 验证
mysql -u root -pmypwd -e "SELECT 1 AS ok;"
后续完善
创建免密配置文件
改完密码后,每次敲 mysql -u root -pmypwd 很麻烦,而且密码会留在 shell 历史里。创建 /root/.my.cnf:
[client]
user=root
password=mypwd
chmod 600 /root/.my.cnf
# 之后直接 mysql -e "..." 即可
同步所有配置文件
密码改了,但服务器上还有多个脚本硬编码了旧密码:
/opt/english-api/fix_phonetics.py
/opt/english-api/fix_worker.py
/opt/english-api/extract_answers.py
/opt/english-api/link_audio.py
/opt/english-api/link_audio2.py
# 全部 sed 替换 english_app_pass → mypwd
本地也一样——CLAUDE.md 和知识库 memory 文件里的连接串也要更新。
完整操作 checklist
总结一个”安全更换数据库密码”的步骤,下次照着做就不会踩坑:
- 确认知道 root 密码(不知道就先 reset)
- 改 MySQL 用户密码:
ALTER USER 'xxx'@'localhost' IDENTIFIED BY 'newpass'; FLUSH PRIVILEGES; - 改应用配置文件:
config.py里的连接串 - 改所有硬编码脚本:grep 全局搜索旧密码,逐一替换
- 重启应用服务:
systemctl restart english-api - 验证连接:
mysql -u xxx -pnewpass -e "SELECT 1" - 更新文档:CLAUDE.md、知识库、团队共享的配置说明
- 清理 shell 历史:
history -c避免密码残留
经验教训
- skip-grant-tables 模式下要先 FLUSH PRIVILEGES 再 ALTER USER,否则语法报错
- 非交互 shell 不认
kill %1,用pkill杀进程更可靠 - 密码要全局搜索替换:配置文件、脚本、文档、知识库,少改一处就是一颗定时炸弹
- 创建
~/.my.cnf不仅能免密登录,还能避免密码留在命令历史里
发表回复