have_symlink=no在配置中无效,因其仅为只读状态标识;真正生效的是skip_symbolic_links=yes(须置于[mysqld]段),且必须同步设置local_infile=0并回收file权限,否则仍存在安全风险。

必须用 skip_symbolic_links=yes,写在 [mysqld] 段里,且要同步关掉 local_infile=0 并回收 FILE 权限——只改 have_symlink=NO 或 symbolic-links=0 都无效。
为什么 have_symlink=NO 在配置里写了也白写
have_symlink 是 MySQL 启动时探测操作系统能力后自动设置的只读变量,不是配置项。你往 my.cnf 里写 have_symlink=NO,MySQL 直接忽略,重启后 SHOW VARIABLES LIKE 'have_symlink' 依然显示 YES 是正常现象——它只表示“系统支持符号链接”,不表示“MySQL 允许你用”。真正起作用的是 skip_symbolic_links 这个开关。
skip_symbolic_links=yes 必须写对位置和格式
这个配置只在 [mysqld] 段下生效,写到 [client]、[mysql] 或全局段都无效。MySQL 5.7 属于 5.6+ 版本,symbolic-links=0 已废弃,部分环境(如某些 Docker 镜像或 8.0.33+ 衍生版)会直接无视它并静默启用符号链接。
- 正确写法:
[mysqld] skip_symbolic_links=yes
- 不要和
symbolic-links=0共存,避免被后者覆盖或引发冲突 - 确认配置文件路径:常见为
/etc/my.cnf、/etc/mysql/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf;用find / -name my.cnf 2>/dev/null确认实际加载的是哪个 - 改完必须重启服务:
systemctl restart mysqld(或service mysql restart)
光禁符号链接还不够:local_infile=0 和权限必须同步做
即使 skip_symbolic_links=yes 生效了,攻击者仍可能通过 LOAD DATA INFILE 加载本地敏感文件(比如 /proc/self/environ),只要 local_infile 开着、用户有 FILE 权限。
- 在同一个
[mysqld]段下加:local_infile=0
- 执行
SELECT @@skip_symbolic_links;应返回1,SHOW VARIABLES LIKE 'local_infile';应返回OFF - 检查用户权限:
SELECT User, Host, File_priv FROM mysql.user;,对非必要账号执行REVOKE FILE ON *.* FROM 'username'@'host'; - 验证行为是否真被阻断:运行
CREATE TABLE t1 (id INT) DATA DIRECTORY='/tmp/test';,应报错ERROR 1030 (HY000): Got error 168 from storage engine
容易被忽略的验证盲点
很多人只查 @@skip_symbolic_links 返回 1 就以为万事大吉,但实际配置可能根本没加载成功。最可靠的验证是触发路径解析行为:
- 确认
mysqld进程读的是你改的那个my.cnf:启动时加--verbose --help | grep "Default options"查默认配置路径 - 检查错误日志:
tail -n 20 /var/log/mysql/error.log,看是否有Warning: Skipping creation of symbolic links类提示 - 如果
DATA DIRECTORY语句仍成功执行,说明配置未生效——90% 是配置文件路径错、没重启、或被其他my.cnf覆盖
安全不是单点开关,是配置 + 权限 + 行为验证三层落地。漏掉任意一层,skip_symbolic_links=yes 就只是个摆设。











