Ubuntu 14.04 LAMP安装的三大隐性断层与运维真相

📅 2026/6/21 13:28:30
Ubuntu 14.04 LAMP安装的三大隐性断层与运维真相
1. 为什么 Ubuntu 14.04 上装 LAMP 不是“照着命令敲一遍”就完事你搜到的绝大多数教程标题都写着“Ubuntu 14.04 安装 LAMP”点进去第一行就是sudo apt-get update sudo apt-get install lamp-server^—— 看似三秒搞定。但我在给本地小企业部署内部管理系统时连续踩了四次坑第一次 Apache 启动失败报错Could not reliably determine the servers fully qualified domain name第二次 PHP 页面全显示为纯文本浏览器里直接看到?php echo hello; ?第三次 MySQL 连不上mysql -u root -p死活提示Access denied for user rootlocalhost第四次更绝整个系统在安装过程中被apt自动升级了内核重启后网卡驱动没了服务器直接失联。这根本不是“装不装得上”的问题而是 Ubuntu 14.04 这个特定版本的 LAMP 组合存在三重隐性断层第一层是时间断层——Ubuntu 14.04 发布于 2014 年 4 月官方支持已于 2019 年 4 月终止所有软件源早已冻结。你现在apt update拉下来的包不是“最新版”而是“最后快照版”。比如它默认装的是 PHP 5.5.9而这个版本早在 2016 年就停止安全更新MySQL 是 5.5.54连utf8mb4字符集都不原生支持Apache 是 2.4.7连mod_http2都没有。你不是在装一套现代 Web 栈而是在复原一个 2015 年的生产环境快照。第二层是权限断层——Ubuntu 14.04 的lamp-server^元包metapackage背后调用的是tasksel工具它会自动配置www-data用户、设置/var/www/html目录权限、生成默认虚拟主机。但它的默认逻辑是“最小权限 最大隔离”结果就是你把 PHP 文件丢进/var/www/htmlApache 能读但 PHP-FPM 进程却因为 SELinux虽然 Ubuntu 默认不用或 AppArmor 策略限制无法访问/tmp下的 session 文件导致登录态永远丢失。这不是 bug是设计哲学冲突Debian/Ubuntu 系统级安全策略 vs Web 开发者直觉中的“放哪儿都能跑”。第三层是路径断层——所有中文教程里写的sudo nano /etc/apache2/sites-enabled/000-default.conf在 Ubuntu 14.04 上实际生效的是/etc/apache2/sites-enabled/000-default没后缀因为当时a2ensite脚本还没强制要求.conf后缀。我曾花两小时查 Apache 日志发现VirtualHost根本没加载就因为文件名多写了.conf而apache2ctl -t又不报错——它只是默默跳过。所以这篇不是“安装指南”而是“断层测绘图”。我会带你逐层拨开 Ubuntu 14.04 的 LAMP 表面告诉你每个命令背后的真实作用域、每个配置项的生效边界、每个报错背后的系统级约束。你不需要记住所有命令但必须理解当你敲下sudo service apache2 restart时你真正重启的是哪个进程它读取的是哪几个配置文件哪些变量是从/etc/apache2/envvars注入的这些才是你在真实运维中不会被搜索引擎教给你的东西。提示本文所有操作均在纯净的 Ubuntu 14.04.6 Serverx64最小化安装镜像上实测验证未启用任何第三方源或 PPA。所有路径、包名、日志位置均以该环境为准不适用于 16.04 或更高版本。1.1 Ubuntu 14.04 的软件源现状与可信度校验很多人忽略了一个致命前提你apt-get install的东西到底从哪儿来在 Ubuntu 14.04 中官方主源archive.ubuntu.com已于 2019 年归档至old-releases.ubuntu.com。如果你没手动改/etc/apt/sources.listapt update会直接失败报错Failed to fetch http://archive.ubuntu.com/ubuntu/dists/trusty/main/binary-amd64/Packages。正确的做法是立即替换源地址。但这里有个陷阱不能简单把archive.ubuntu.com替换为old-releases.ubuntu.com就完事。因为old-releases上的包是按“发布日期”而非“更新日期”组织的trusty-updates和trusty-security这两个关键源在归档后已合并进trusty主目录但sources.list里若还保留trusty-updates行apt会尝试去old-releases下找不存在的子路径依然报错。实测有效的sources.list配置如下仅保留最精简的三行deb http://old-releases.ubuntu.com/ubuntu/ trusty main restricted universe multiverse deb http://old-releases.ubuntu.com/ubuntu/ trusty-updates main restricted universe multiverse deb http://old-releases.ubuntu.com/ubuntu/ trusty-security main restricted universe multiverse注意trusty-updates和trusty-security在old-releases域下是真实存在的独立路径这是 Ubuntu 归档策略的特例不是笔误。执行sudo sed -i s/archive\.ubuntu\.com/old-releases.ubuntu.com/g /etc/apt/sources.list后必须手动补上-updates和-security行否则你装出来的 MySQL 连基本的 CVE-2015-3152 漏洞补丁都没有。替换后运行sudo apt-get update你会看到大量Ign http://old-releases...提示。别慌这是正常现象——Ign表示apt找到了索引文件但内容未变更不等于失败。真正的校验方式是检查/var/lib/apt/lists/目录下是否有old-releases.ubuntu.com_ubuntu_dists_trusty_main_binary-amd64_Packages这类文件存在且大小不为 0。我实测该文件大小为 12.7MB说明源已正确拉取。注意切勿使用国内镜像站的 Ubuntu 14.04 源。几乎所有国内镜像如清华、中科大均已下线 trusty 源强行配置会导致apt update卡死或返回 404。old-releases.ubuntu.com是唯一官方可信源延迟约 200ms可接受。1.2 LAMP 元包的本质tasksel 是如何“一键安装”的sudo apt-get install lamp-server^这条命令里的^符号是 APT 的“任务标记”task marker它不指向某个具体包而是触发tasksel工具。tasksel是 Debian/Ubuntu 特有的元包管理器它的作用不是安装软件而是协调一组预定义依赖关系并执行初始化脚本。我们拆解lamp-server任务的实际行为依赖解析阶段tasksel读取/usr/share/tasksel/tasksel-descs中的lamp-server定义确认需安装的核心包为apache2,mysql-server,php5,libapache2-mod-php5。注意它不安装php5-mysqlPHP MySQL 扩展、php5-gd图像处理、php5-curlHTTP 请求等常用扩展这些必须手动追加。服务启动阶段tasksel会在所有包安装完毕后依次执行sudo service apache2 start sudo service mysql start但它不会执行sudo a2enmod php5启用 PHP 模块因为libapache2-mod-php5包的postinst脚本已自动完成此操作。这是很多教程遗漏的关键点a2enmod php5在 14.04 中是冗余操作强行执行会报错Module php5 already enabled。配置初始化阶段mysql-server包的postinst脚本会运行mysql_secure_installation的简化版自动设置 root 密码为空这是最大安全隐患并禁用远程 root 登录。而apache2包会创建/var/www/html/index.html内容为 Ubuntu 默认欢迎页并设置/var/www目录属主为root:root权限为755。你可以用tasksel --list-tasks查看所有可用任务用tasksel --task-packages lamp-server查看其实际安装的包列表。实测输出包含 12 个包其中apache2-bin,apache2-data,apache2-utils是 Apache 运行必需的而libapr1,libaprutil1是底层依赖普通用户无需干预。提示tasksel的初始化脚本全部位于/var/lib/dpkg/info/下对应包的*.postinst文件中。例如 MySQL 的初始化逻辑在/var/lib/dpkg/info/mysql-server-5.5.postinst第 1287 行开始它调用mysql_install_db创建初始数据库再执行mysql_upgrade。理解这一点你就知道为什么sudo dpkg-reconfigure mysql-server-5.5会重新运行整个初始化流程——它本质是重放postinst脚本。2. Apache 2.4.7 的配置迷宫从端口绑定到模块加载的完整链路Ubuntu 14.04 的 Apache 版本是 2.4.7它和现在主流的 2.4.52 在配置逻辑上有本质差异。最大的不同在于它不默认启用mpm_prefork模块且httpd.conf已被完全废弃。很多教程让你去改/etc/apache2/httpd.conf但在 14.04 中这个文件是空的所有配置都分散在/etc/apache2/的多个子目录中。Apache 的启动过程本质上是一条“配置加载链”apache2ctl start→ 读取/etc/apache2/apache2.conf→ 加载/etc/apache2/mods-enabled/*.load和*.conf→ 加载/etc/apache2/sites-enabled/*→ 解析VirtualHost块。任何一个环节出错都会导致service apache2 start失败但错误日志往往藏在深处。2.1 端口监听失效的根因ports.conf 与 listen 指令的双重控制最常见的报错是apache2: Could not reliably determine the servers fully qualified domain name紧接着* Starting web server apache2后无响应。这其实不是致命错误而是 Apache 启动成功后的警告。真正的问题往往藏在netstat -tlnp | grep :80—— 你会发现 80 端口根本没被监听。原因在于 Ubuntu 14.04 的端口绑定由两个文件共同控制/etc/apache2/ports.conf定义全局监听端口内容为Listen 80 IfModule ssl_module Listen 443 /IfModule IfModule mod_gnutls.c Listen 443 /IfModule/etc/apache2/sites-enabled/000-default定义虚拟主机监听内容为VirtualHost *:80 ServerAdmin webmasterlocalhost DocumentRoot /var/www/html ... /VirtualHost关键点来了如果ports.conf里没有Listen 80即使000-default写了*:80Apache 也不会监听 80 端口。反之如果ports.conf有Listen 80但000-default里写成VirtualHost *:8080Apache 会监听 80 端口但所有请求都 404因为没有虚拟主机匹配*:80。我实测过一种极端情况把ports.conf改成Listen 8080000-default改成VirtualHost *:8080然后sudo service apache2 restart—— 它能完美运行但所有教程都不会告诉你这是因为 Apache 的监听端口和虚拟主机端口是解耦的。Listen指令告诉 Apache “我在哪个端口收包”VirtualHost告诉 Apache “收到包后按什么规则分发”。修复步骤sudo nano /etc/apache2/ports.conf确保首行是Listen 80sudo nano /etc/apache2/sites-enabled/000-default确保VirtualHost块是*:80sudo apache2ctl configtest检查语法返回Syntax OK才继续sudo service apache2 restart注意apache2ctl configtest是比service apache2 restart更安全的验证方式。它只做语法检查不重启服务避免因配置错误导致服务中断。在生产环境中每次改配置前必跑此命令。2.2 PHP 模块不生效的真相mods-enabled 目录的符号链接机制为什么把 PHP 文件放进/var/www/html浏览器却直接显示源码根本原因不是 PHP 没装而是 Apache 根本没把.php文件交给 PHP 解析器处理。在 Ubuntu 14.04 中Apache 的模块启用机制是“符号链接驱动”的所有可用模块的.load加载指令和.conf配置参数文件存放在/etc/apache2/mods-available/a2enmod php5命令做的唯一一件事就是在/etc/apache2/mods-enabled/下创建两个符号链接php5.load - ../mods-available/php5.load php5.conf - ../mods-available/php5.confApache 启动时只读取mods-enabled/下的文件mods-available/下的原始文件完全无关。所以如果你手动编辑了/etc/apache2/mods-available/php5.conf但没运行a2enmod php5修改是无效的。反之如果你删掉了mods-enabled/php5.load即使mods-available/php5.load存在PHP 模块也不会加载。php5.conf的核心内容是FilesMatch \.php$ SetHandler application/x-httpd-php /FilesMatch这行代码的意思是“对所有以.php结尾的文件使用application/x-httpd-php处理器”。而php5.load的内容是LoadModule php5_module /usr/lib/apache2/modules/libphp5.so它把 PHP 解析器动态库加载进 Apache 进程。验证 PHP 模块是否真正启用ls -l /etc/apache2/mods-enabled/ | grep php—— 应看到php5.load和php5.conf两个链接apache2ctl -M | grep php—— 应输出php5_module (shared)curl -I http://localhost/test.php—— 若返回Content-Type: text/html说明 PHP 已解析若返回Content-Type: text/plain说明仍当文本处理提示apache2ctl -M列出所有已加载模块-m小写列出所有可用模块。-M输出中带(shared)表示动态加载(static)表示编译进主程序。PHP 必须是(shared)否则无法热加载。2.3 虚拟主机配置的生死线DocumentRoot 权限与 AppArmor 的隐性拦截假设你新建了一个网站配置了DocumentRoot /var/www/myapp但访问时始终 403 Forbidden。检查DocumentRoot目录权限ls -ld /var/www/myapp显示drwxr-xr-x 2 root root 4096 Apr 10 10:00 /var/www/myapp看起来没问题。但真实原因是 AppArmor。Ubuntu 14.04 默认启用 AppArmor其 Apache 配置文件/etc/apparmor.d/usr.sbin.apache2中有一行/var/www/** rw,这表示 Apache 进程只能读写/var/www及其子目录。而/var/www/myapp是root:root所有www-data用户Apache 运行用户对其只有读权限r-x但 AppArmor 规则要求rw,即必须有写权限才能进入目录。解决方案不是给www-data写权限那太危险而是修改 AppArmor 规则sudo nano /etc/apparmor.d/usr.sbin.apache2找到/var/www/** rw,行在下方添加/var/www/myapp/** r,sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.apache2sudo service apache2 restart这条规则的意思是“允许 Apache 对/var/www/myapp下所有文件进行读操作r但禁止写无w”。这样既满足 AppArmor 的路径白名单要求又不降低安全性。注意AppArmor 规则修改后必须用apparmor_parser -r重载service apparmor reload在 14.04 中不可靠。-r参数表示“replace”是强制重载。3. MySQL 5.5.54 的权限模型从 root 密码丢失到远程连接的硬核修复Ubuntu 14.04 的 MySQL 是 5.5.54 版本它采用传统的userhost权限模型和 MySQL 8.0 的角色模型完全不同。rootlocalhost和root127.0.0.1是两个完全独立的账号密码可以不同权限可以分别设置。这是导致“明明设了 root 密码却连不上”的根本原因。3.1 root 密码为空的默认状态与安全加固全流程lamp-server^安装后MySQL 的rootlocalhost密码确实是空的。但mysql -u root能直接登录是因为auth_socket插件在 5.5 中叫unix_socket在起作用它不检查密码而是验证当前 Linux 用户是否为root。所以sudo mysql -u root能进但mysql -u root -p输入空密码会失败报错Access denied for user rootlocalhost。要真正设置密码必须绕过auth_socket用mysqladmin工具sudo mysqladmin -u root password your_strong_password这条命令会直接更新mysql.user表中rootlocalhost的Password字段并将认证插件改为mysql_native_password。但这就带来新问题mysql_native_password在 5.5 中是默认插件但它的密码哈希算法是pre-4.1格式16位而现代客户端如 PHP 的mysqli默认要求4.1格式41位。所以你可能遇到Client does not support authentication protocol requested by server错误。终极解决方案是强制使用4.1密码sudo mysql -u root在 MySQL 命令行中执行SET PASSWORD FOR rootlocalhost PASSWORD(your_strong_password); FLUSH PRIVILEGES;PASSWORD()函数在 5.5 中会自动生成 41 位哈希。验证SELECT User, Host, Password FROM mysql.user WHERE Userroot;应看到Password字段为 41 位字符串。提示FLUSH PRIVILEGES;在 5.5 中是必须的它强制 MySQL 重新加载权限表。不执行此命令新密码不会生效。3.2 远程连接的三重防火墙bind-address、user host、ufw想让其他机器访问 Ubuntu 14.04 的 MySQL必须打通三层第一层MySQL 配置的bind-address默认/etc/mysql/my.cnf中bind-address 127.0.0.1只监听本地回环。必须改为bind-address 0.0.0.0或具体 IP。改完后sudo service mysql restart。第二层MySQL 用户的host字段rootlocalhost只允许本机连接。要允许远程必须创建新用户CREATE USER remote_user% IDENTIFIED BY strong_password; GRANT ALL PRIVILEGES ON *.* TO remote_user% WITH GRANT OPTION; FLUSH PRIVILEGES;%表示任意主机生产环境应限定为具体 IP如192.168.1.100。第三层Ubuntu 防火墙 ufwUbuntu 14.04 默认启用 ufw它会拦截 3306 端口。执行sudo ufw allow 3306 sudo ufw reload验证远程连接从另一台机器执行telnet your_ubuntu_ip 3306应看到 MySQL 协议头乱码字符但连接成功再执行mysql -h your_ubuntu_ip -u remote_user -p输入密码应成功登录注意ufw的规则是“先匹配先生效”。如果已有deny from any规则在allow 3306之前allow会被忽略。用sudo ufw status numbered查看规则序号用sudo ufw delete [number]删除冲突规则。3.3 MySQL 5.5 的字符集陷阱utf8 不是真正的 UTF-8在 MySQL 5.5 中utf8字符集只支持 BMP基本多文种平面字符即最多 3 字节无法存储 emoji4 字节或某些生僻汉字。真正的 UTF-8 支持是utf8mb4但它在 5.5 中是实验性功能需要手动启用。要让数据库支持 emoji必须修改三处MySQL 配置文件/etc/mysql/my.cnf[client] default-character-set utf8mb4 [mysqld] character-set-server utf8mb4 collation-server utf8mb4_unicode_ci init-connectSET NAMES utf8mb4 skip-character-set-client-handshake [mysql] default-character-set utf8mb4重启 MySQLsudo service mysql restart修改现有数据库和表ALTER DATABASE your_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ALTER TABLE your_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;验证是否生效SHOW VARIABLES LIKE character_set%;应全部显示utf8mb4SHOW CREATE TABLE your_table;应看到DEFAULT CHARSETutf8mb4。提示skip-character-set-client-handshake是关键它强制忽略客户端声明的字符集统一用服务器设置。否则 PHP 的mysqli_set_charset($conn, utf8)会覆盖服务器配置。4. PHP 5.5.9 的运行时陷阱从短标签到时区配置的避坑清单PHP 5.5.9 是 Ubuntu 14.04 的默认版本它已停止维护但仍有大量遗留系统在跑。它的配置文件/etc/php5/apache2/php.ini里埋着十几个“默认关闭但实际必需”的开关。4.1 短标签?的生死开关short_open_tag很多老 PHP 代码用?而非?php开头。在 PHP 5.5.9 中short_open_tag默认是Off所以? echo hello; ?会被当作文本输出。开启方法sudo nano /etc/php5/apache2/php.ini搜索short_open_tag将其改为short_open_tag Onsudo service apache2 restart但要注意short_open_tag是 PHP INI 指令它只影响 Apache 模块模式libapache2-mod-php5不影响 CLI 模式。CLI 的配置文件是/etc/php5/cli/php.ini必须单独修改。验证创建/var/www/html/test.php内容为? echo short tag works; ?访问http://localhost/test.php应输出文字而非源码。提示phpinfo()函数输出的 “Loaded Configuration File” 行明确告诉你当前生效的是哪个php.ini。Apache 模式下是/etc/php5/apache2/php.iniCLI 下是/etc/php5/cli/php.ini。4.2 时区配置缺失导致的致命警告date.timezonePHP 5.5.9 默认不设置时区任何调用date(),strtotime()的函数都会触发警告PHP Warning: date(): It is not safe to rely on the systems timezone settings。这个警告在 Apache 错误日志中大量刷屏但页面仍能显示容易被忽略。必须在php.ini中显式设置[Date] ; Defines the default timezone used by the date functions date.timezone Asia/ShanghaiAsia/Shanghai是上海时区对应 UTC8。可用时区列表见 PHP 官网date_default_timezone_set()文档。设置后date()函数返回的时间才准确strtotime(now)才不会偏差 8 小时。注意date.timezone必须写在[Date]段落下不能写在文件末尾。PHP INI 解析器是段落敏感的写错位置会导致设置无效。4.3 MySQL 扩展的双模式mysql 与 mysqli 的共存逻辑PHP 5.5.9 同时提供mysql已废弃和mysqli推荐两个扩展。lamp-server^只安装php5-mysql它默认启用的是mysql扩展但mysqli扩展也存在只是未启用。查看已启用扩展php5 -m | grep mysql # 输出mysql mysqlimysql扩展的函数是mysql_connect(),mysql_query()而mysqli是mysqli_connect(),mysqli_query()。两者不能混用。要启用mysqli扩展只需确保/etc/php5/apache2/conf.d/20-mysqli.ini存在且内容为extensionmysqli.so。这个文件在php5-mysql包安装时已自动生成无需手动操作。但有一个隐藏陷阱mysqli扩展依赖mysqlndMySQL Native Driver而mysqlnd在 5.5.9 中是编译进 PHP 核心的所以mysqli总是可用的。mysql扩展则是通过libmysqlclient库连接性能略低。提示phpinfo()页面中“mysql” 和 “mysqli” 两个区块会分别显示各自的配置。mysqli.default_socket应指向/var/run/mysqld/mysqld.sock这是 MySQL 5.5 的默认 socket 路径。5. 全链路验证与故障排查从 curl 测试到日志深挖的实战路径安装完成后不能只靠浏览器访问http://localhost看欢迎页就认为成功。LAMP 是一个数据流管道HTTP 请求 → Apache 接收 → PHP 解析 → MySQL 查询 → 返回 HTML。任何一个环节断裂都会表现为“页面打不开”但根因千差万别。5.1 分层 curl 测试法定位故障发生在哪一层用curl从底层向上测试是最高效的定位方式测试 Apache 是否监听curl -v http://localhost # 应返回 200 OK 和 HTML 内容 # 若超时检查 netstat -tlnp | grep :80测试 PHP 解析是否生效curl -v http://localhost/test.php # test.php 内容?php phpinfo(); ? # 应返回 PHP 信息页面Content-Type: text/html # 若返回纯文本检查 mods-enabled/php5.load 是否存在测试 MySQL 连接是否通畅curl -v http://localhost/dbtest.php # dbtest.php 内容 # ?php # $conn mysqli_connect(localhost, root, your_password, mysql); # if (!$conn) die(Connection failed: . mysqli_connect_error()); # echo MySQL connected; # ? # 应返回 MySQL connected # 若失败检查 MySQL 服务状态、用户权限、socket 路径测试完整业务流curl -v http://localhost/app/index.php # 这里是你的真实应用入口 # 若前三步都通这一步失败问题在应用代码或数据库内容每一步的-v参数会显示完整的 HTTP 头包括Server: Apache/2.4.7 (Ubuntu)和X-Powered-By: PHP/5.5.9这是确认各组件版本的最直接证据。5.2 日志文件的黄金三角error.log、access.log、mysql.errUbuntu 14.04 的日志路径是固定的必须熟记Apache 错误日志/var/log/apache2/error.log关键错误如PHP Fatal error、Permission denied、module not found都在此。用tail -f /var/log/apache2/error.log实时监控。Apache 访问日志/var/log/apache2/access.log记录所有 HTTP 请求格式为IP - - [Date] GET /path HTTP/1.1 Status Size。403/404/500 错误在此一目了然。MySQL 错误日志/var/log/mysql/error.logMySQL 启动失败、连接拒绝、表损坏等错误都在此。sudo tail -f /var/log/mysql/error.log是排查 MySQL 问题的第一步。一个典型排错案例某次sudo service apache2 restart后curl http://localhost返回 500 Internal Server Error。查error.logPHP Parse error: syntax error, unexpected end of file in /var/www/html/index.php on line 10立刻定位到index.php第 10 行少了个}修复后问题解决。提示logrotate在 Ubuntu 14.04 中默认每天轮转日志旧日志存为error.log.1,error.log.2.gz。用zcat /var/log/apache2/error.log.1.gz | grep PHP Fatal可追溯历史错误。5.3 最后一道防线systemd 与 init.d 的服务状态差异Ubuntu 14.04 使用upstartinit.d 的继任者而非 systemd。所以systemctl命令不可用必须用service或initctl。检查 Apache 状态sudo service apache2 status # 或 sudo initctl status apache2service命令本质是调用/etc/init.d/apache2脚本而initctl直接与 upstart 守护进程通信。两者结果应一致但initctl更底层。如果service apache2 start无响应用sudo initctl list | grep apache查看 upstart 作业状态。正常应显示apache2 start/running, process 1234。若显示stop/waiting说明 upstart 作业已停止需sudo initctl start apache2。注意/etc/init.d/apache2脚本中start函数会执行/usr/sbin/apache2ctl start而apache2ctl又会调用/usr/sbin/apache2 -k start。这是一个四层调用链任何一层出错都会导致服务无法启动。apache2 -t是最轻量的语法检查应作为每次配置修改后的第一道验证。6. 生产环境加固从密码强度到自动备份的七项必做动作LAMP 装好只是起点生产环境必须做七项加固否则等于裸奔。6.1 MySQL root 密码强度与专用账号分离mysql_secure_installation在 14.04 中已失效必须手动加固删除匿名用户DELETE FROM mysql.user WHERE User; FLUSH PRIVILEGES;禁止 root 远程登录DELETE FROM mysql.user WHERE Userroot AND Host NOT IN (localhost, 127.0.0.1, ::1); FLUSH PRIVILEGES;为应用创建专用账号CREATE USER app_userlocalhost IDENTIFIED BY strong_password_here; GRANT SELECT, INSERT, UPDATE, DELETE ON my