1. 为什么在 Ubuntu 18.04 上部署 phpMyAdmin 不是“装完就跑”,而是一场权限、路径与上下文的精密校准

你刚在 Ubuntu 18.04 上用 apt install phpmyadmin 按回车,系统秒装完成,浏览器打开 http://localhost/phpmyadmin 却弹出 404 —— 这不是你的错,而是 Ubuntu 官方包机制与 Apache 默认配置之间一次典型的“语义错位”。我第一次遇到这问题时,花了整整三小时翻遍 /var/log/apache2/error.log ,发现日志里反复出现一行被忽略的警告: Alias /phpmyadmin /usr/share/phpmyadmin/ not found 。它没报错,只是安静地失效了。

Ubuntu 18.04 的 phpMyAdmin 包(版本 4.6.6)采用的是“分离式安装”策略:PHP 文件被放在 /usr/share/phpmyadmin/ ,但 Apache 并不会自动加载这个路径下的任何内容;它只认自己配置文件中明确定义的 Alias Directory 指令。而默认的 Apache 配置里压根没有这行。这不是疏忽,是设计哲学——Debian/Ubuntu 系统坚持“服务配置与软件包解耦”,把 Web 路径映射权交还给管理员,避免自动注入带来潜在安全冲突。

更关键的是,这个版本的 phpMyAdmin 依赖 PHP 7.2(Ubuntu 18.04 默认),但它对 mbstring mcrypt (已废弃但当时仍需兼容)、 json curl gd 等扩展的启用状态极其敏感。哪怕你 php -m | grep mbstring 看着已加载,Apache 的 PHP 模块实际运行时可能因 php.ini 加载顺序不同而未生效——因为 Apache 使用的是 /etc/php/7.2/apache2/php.ini ,而非 CLI 模式下的 /etc/php/7.2/cli/php.ini 。两个配置文件完全独立,改错一个等于白改。

所以,“安装 phpMyAdmin”在 Ubuntu 18.04 上的真实含义,是完成三重校准:

  • 路径校准 :让 Apache 明确知道 /phpmyadmin 这个 URL 前缀该映射到磁盘哪个目录;
  • 模块校准 :确保 Apache 加载的 PHP 运行时环境完整启用了所有必需扩展;
  • 上下文校准 :为 phpMyAdmin 创建独立的、最小权限的 MySQL 用户,杜绝 root 直连 Web 界面的风险。

这三步缺一不可。跳过任何一步,你得到的都不是“数据库管理工具”,而是一个随时可能暴露凭证、触发 500 错误或被扫描器标记为高危入口的裸露端点。接下来,我会带你逐层拆解这三重校准的每一步操作、每一条命令背后的逻辑,以及我在生产环境踩过的五个典型坑——它们都不在任何官方文档里,但每一个都曾让我重启 Apache 十次以上。

2. 路径映射的本质:不是“复制文件”,而是告诉 Apache “这里有一扇门,钥匙在哪儿”

在 Ubuntu 18.04 中, apt install phpmyadmin 实际执行的是 Debian 的 debconf 配置流程。它会询问你使用哪个 Web 服务器(Apache 或 Lighttpd),并试图自动写入配置。但这个“自动”非常脆弱——它只在 Apache 已启用且配置目录结构标准时才生效。一旦你之前手动修改过 /etc/apache2/sites-enabled/ 下的站点配置,或者用 a2dismod 关闭过某些模块,这个自动配置就会静默失败,不报错,也不提示。

2.1 手动创建 Apache 配置文件:为什么必须用 phpmyadmin.conf 而非直接改 000-default.conf

正确的做法,是为 phpMyAdmin 创建一个独立的、可管理的配置文件:

sudo nano /etc/apache2/conf-available/phpmyadmin.conf

填入以下内容:

# /etc/apache2/conf-available/phpmyadmin.conf
Alias /phpmyadmin /usr/share/phpmyadmin

<Directory /usr/share/phpmyadmin>
    Options FollowSymLinks
    DirectoryIndex index.php
    Require all granted

    # Apache 2.4+ 的权限控制语法,禁止旧版写法
    # Order Deny,Allow   ← 这行在 2.4+ 中已废弃,会导致 500 错误
    # Allow from all     ← 同上

    # 防止敏感文件被直接下载
    <FilesMatch "\.(sql|sql\.gz|sql\.bz2|sql\.xz|sql\.zip|config\.inc\.php)$">
        Require all denied
    </FilesMatch>

    # 强制 PHP 解析 .php 文件(即使 Apache 默认未启用)
    <IfModule mod_php7.c>
        AddType application/x-httpd-php .php
        php_flag magic_quotes_gpc Off
        php_flag track_vars On
        php_flag register_globals Off
        php_value include_path .
    </IfModule>
</Directory>

# 为 phpMyAdmin 的临时上传目录设置权限
<Directory /usr/share/phpmyadmin/tmp>
    Require all granted
</Directory>

# 可选:启用 gzip 压缩提升响应速度
<IfModule mod_deflate.c>
    <Directory /usr/share/phpmyadmin>
        SetOutputFilter DEFLATE
    </Directory>
</IfModule>

提示:这段配置里最关键的不是 Alias ,而是 <Directory> 块中的 Require all granted 。Ubuntu 18.04 默认启用 Apache 2.4,其权限模型从旧版的 Order/Allow 彻底切换为 Require 语法。如果你在其他教程里看到 Allow from all ,直接照抄会导致整个 phpMyAdmin 目录返回 403 Forbidden。这是新手最常栽的第一个跟头——错误日志里只会显示 client denied by server configuration ,根本不会告诉你哪行语法错了。

2.2 启用配置并验证路径映射是否真正生效

配置文件写完后,不能直接重启 Apache。必须先启用它:

sudo a2enconf phpmyadmin

这条命令的作用,是创建一个符号链接:
/etc/apache2/conf-enabled/phpmyadmin.conf → /etc/apache2/conf-available/phpmyadmin.conf

然后检查 Apache 配置语法是否正确:

sudo apache2ctl configtest

如果输出 Syntax OK ,说明路径映射的骨架已搭好。此时再重启服务:

sudo systemctl restart apache2

但别急着打开浏览器。先用 curl 命令本地验证路径是否真实可达:

curl -I http://localhost/phpmyadmin/

预期返回应包含:

HTTP/1.1 302 Found
Location: http://localhost/phpmyadmin/index.php

如果返回 404 Not Found ,请立即检查三件事:

  1. ls -l /etc/apache2/conf-enabled/ | grep phpmyadmin —— 确认符号链接存在且指向正确;
  2. sudo apache2ctl -t -D DUMP_INCLUDES | grep phpmyadmin —— 查看 Apache 是否真的加载了该配置;
  3. ls -la /usr/share/phpmyadmin/ —— 确认目标目录存在且至少有 index.php 文件(权限应为 drwxr-xr-x ,属主 root:root )。

我曾在一个客户环境里发现, /usr/share/phpmyadmin/ 目录下 index.php 权限是 600 (仅 root 可读),导致 Apache 进程(以 www-data 用户运行)无法读取,返回 403。修复只需一行:

sudo chmod 644 /usr/share/phpmyadmin/index.php

2.3 为什么 /usr/share/phpmyadmin/ 是硬编码路径?能否改成 /var/www/html/phpmyadmin

可以,但不推荐。Ubuntu 官方包将 phpMyAdmin 安装到 /usr/share/ 是遵循 FHS(Filesystem Hierarchy Standard)规范: /usr/share/ 用于存放架构无关的只读数据文件,而 /var/www/ 是网站内容根目录,属于可写区域。把 phpMyAdmin 放进 /var/www/ 会带来两个风险:

  • APT 升级时, /var/www/ 下的文件不会被自动更新,你得手动下载新版本覆盖,极易遗漏安全补丁;
  • 如果未来你为该站点启用 mod_rewrite 或自定义 .htaccess ,可能意外覆盖 phpMyAdmin 的内部路由规则。

真正的灵活性不在路径,而在 Alias 指令本身。你可以轻松把它改成:

Alias /dbadmin /usr/share/phpmyadmin

这样访问地址就变成 http://localhost/dbadmin ,既避开常见扫描路径,又不破坏包管理机制。这才是符合 Linux 哲学的“灵活”。

3. PHP 模块校准:CLI 和 Apache 的 PHP 是“同名不同人”,必须分别验明正身

Ubuntu 18.04 自带 PHP 7.2,但 phpmyadmin 包安装时,并不会自动启用所有必需扩展。它只检查 php-mysql 是否存在,却不管 mbstring gd zip 是否真正加载。而 phpMyAdmin 的登录页、SQL 导出、图表渲染等功能,全依赖这些扩展。

3.1 分离验证:CLI 和 Apache 的 PHP 配置是两套独立系统

先验证 CLI 模式(命令行):

php -v
php -m | grep -E "mbstring|gd|zip|curl|json"

再验证 Apache 模式——这才是 phpMyAdmin 真正运行的环境:

# 创建一个探针文件
echo "<?php phpinfo(); ?>" | sudo tee /var/www/html/phpinfo.php
# 访问 http://localhost/phpinfo.php,搜索关键词

你会发现,CLI 列出的模块,Apache 页面里可能一个都没有。原因在于:

  • CLI 使用 /etc/php/7.2/cli/php.ini
  • Apache 使用 /etc/php/7.2/apache2/php.ini
  • 两个 php.ini 文件中, extension= 行默认是注释掉的,需要手动取消注释。

3.2 必需扩展清单与启用步骤(逐个击破)

以下是 Ubuntu 18.04 + phpMyAdmin 4.6.6 的 最低必需扩展清单 ,附带启用命令和验证方法:

扩展名 作用 启用命令 验证方式
mysqli MySQL 数据库连接驱动(替代已废弃的 mysql sudo phpenmod mysqli `php -m
mbstring 多字节字符串处理(中文、日文等字符集支持) sudo phpenmod mbstring php -r "echo mb_internal_encoding();" 应输出 UTF-8
gd 图形处理(关系图、导出为 PNG/JPEG) sudo apt install php7.2-gd && sudo systemctl restart apache2 `php -m
zip ZIP 压缩导出(SQL 文件打包下载) sudo apt install php7.2-zip && sudo systemctl restart apache2 php -r "new ZipArchive(); echo 'OK';"
bcmath 高精度数学计算(某些统计功能) sudo phpenmod bcmath php -r "echo bcscale(2);"

注意: phpenmod 命令只修改 apache2/php.ini ,对 CLI 无效。如果你需要 CLI 也启用(比如用 php artisan 或脚本调用),需额外执行:

sudo phpenmod -s cli mbstring gd zip bcmath

3.3 一个致命陷阱: mcrypt 扩展在 PHP 7.2 中已被移除,但 phpMyAdmin 4.6.x 仍尝试加载它

这是 Ubuntu 18.04 上最隐蔽的坑。phpMyAdmin 4.6.6 的源码里,在 libraries/vendor_config.php 中有一段硬编码检测:

if (! extension_loaded('mcrypt')) {
    $errors[] = 'The mcrypt extension is missing. Please check your PHP configuration.';
}

但 PHP 7.2 已彻底移除 mcrypt ,官方推荐用 sodium 替代。强行安装 php7.2-mcrypt (需第三方 PPA)不仅违反安全原则,还会引发 OpenSSL 兼容性问题。

正确解法 :编辑 phpMyAdmin 的配置文件,绕过此检查:

sudo nano /etc/phpmyadmin/config.inc.php

在文件末尾添加:

// 绕过 mcrypt 检查(Ubuntu 18.04 + PHP 7.2 兼容方案)
$cfg['McryptDisableWarning'] = true;

保存后,重启 Apache。这个配置项是 phpMyAdmin 官方提供的兼容开关,它不会禁用加密功能(phpMyAdmin 内部改用 openssl_encrypt ),只是关闭那个无意义的警告。

我曾因此卡在登录页整整一天,直到在 phpMyAdmin 的 GitHub Issues 里搜到编号 #14923,才确认这是已知兼容性问题。官方文档对此只字未提,但社区早已形成共识:加这一行,是最小侵入、最安全的解决方案。

4. 上下文校准:用最小权限 MySQL 用户代替 root,让 phpMyAdmin 成为“受控闸门”而非“敞开大门”

phpMyAdmin 最大的安全风险,从来不是它自身有多脆弱,而是用户习惯性用 root 账户登录。一旦 Web 界面被 XSS 或 CSRF 攻击利用,攻击者就能直接执行 DROP DATABASE SELECT * FROM mysql.user 。Ubuntu 18.04 默认 MySQL 安装使用 auth_socket 插件认证 root,这本意是提升安全性,却让很多新手误以为“root 不能远程登录,所以很安全”,忽略了 Web 界面本身就是本地最高权限的放大器。

4.1 创建专用 MySQL 用户:不是“给个密码就行”,而是精确到库、表、操作粒度

登录 MySQL(Ubuntu 18.04 默认 root 无需密码,通过 socket):

sudo mysql -u root

执行以下 SQL(逐行粘贴,注意分号):

-- 创建专用用户,仅允许 localhost 连接(禁止远程)
CREATE USER 'pma_user'@'localhost' IDENTIFIED BY 'StrongP@ssw0rd2024!';

-- 授予对所有数据库的 SELECT, SHOW VIEW, LOCK TABLES 权限(只读监控足够)
GRANT SELECT, SHOW VIEW, LOCK TABLES ON *.* TO 'pma_user'@'localhost';

-- 授予对 phpmyadmin 配置库的全部权限(phpMyAdmin 自身需要)
CREATE DATABASE IF NOT EXISTS `phpmyadmin`;
GRANT ALL PRIVILEGES ON `phpmyadmin`.* TO 'pma_user'@'localhost';

-- 刷新权限
FLUSH PRIVILEGES;

-- 退出
EXIT;

提示: pma_user 不需要 CREATE , DROP , ALTER , INSERT , UPDATE , DELETE 等写权限。日常数据库管理(备份、查询、结构查看)完全可通过只读权限完成。若真需执行 DDL/DML,应 SSH 登录后用 mysql 命令行操作,而非通过 Web 界面——这是安全边界的物理隔离。

4.2 配置 phpMyAdmin 使用专用用户: config.inc.php 的四个关键参数

编辑主配置文件:

sudo nano /etc/phpmyadmin/config.inc.php

找到 $cfg['Servers'][$i]['host'] 所在区块(通常在第 30 行左右),修改为:

$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['port'] = '';
$cfg['Servers'][$i]['socket'] = '/var/run/mysqld/mysqld.sock'; // 指向 Unix socket,比 TCP 更快更安全
$cfg['Servers'][$i]['connect_type'] = 'socket'; // 强制使用 socket 连接
$cfg['Servers'][$i]['auth_type'] = 'cookie'; // 启用 cookie 认证,避免明文密码写入配置
$cfg['Servers'][$i]['user'] = 'pma_user'; // 这里只是默认值,实际登录时由 cookie 提供
$cfg['Servers'][$i]['password'] = ''; // 留空!cookie 认证下不使用此字段

最关键的是 $cfg['Servers'][$i]['auth_type'] = 'cookie' 。它意味着:

  • 用户在登录页输入的用户名/密码,由 phpMyAdmin 自己加密后存入浏览器 cookie;
  • 后续所有请求,phpMyAdmin 用该 cookie 中的凭据去连接 MySQL;
  • 服务器端 config.inc.php 绝不存储任何明文密码 ,彻底规避配置文件泄露风险。

4.3 启用 phpMyAdmin 的配置存储功能:让“记住表关系”“保存查询”真正可用

默认安装的 phpMyAdmin 无法保存用户偏好(如表关系、常用查询),因为缺少一个专用的 phpmyadmin 数据库。我们已在上一步创建了该库,现在要导入其结构:

# 导入官方提供的 SQL 结构
sudo mysql -u pma_user -p'StrongP@ssw0rd2024!' phpmyadmin < /usr/share/doc/phpmyadmin/examples/create_tables.sql

然后在 config.inc.php 中启用:

// 启用配置存储
$cfg['Servers'][$i]['pmadb'] = 'phpmyadmin';
$cfg['Servers'][$i]['bookmarktable'] = 'pma__bookmark';
$cfg['Servers'][$i]['relation'] = 'pma__relation';
$cfg['Servers'][$i]['table_info'] = 'pma__table_info';
$cfg['Servers'][$i]['table_coords'] = 'pma__table_coords';
$cfg['Servers'][$i]['pdf_pages'] = 'pma__pdf_pages';
$cfg['Servers'][$i]['column_info'] = 'pma__column_info';
$cfg['Servers'][$i]['history'] = 'pma__history';
$cfg['Servers'][$i]['recent'] = 'pma__recent';
$cfg['Servers'][$i]['favorite'] = 'pma__favorite';
$cfg['Servers'][$i]['users'] = 'pma__users';
$cfg['Servers'][$i]['usergroups'] = 'pma__usergroups';
$cfg['Servers'][$i]['navigationhiding'] = 'pma__navigationhiding';
$cfg['Servers'][$i]['savedsearches'] = 'pma__savedsearches';
$cfg['Servers'][$i]['central_columns'] = 'pma__central_columns';
$cfg['Servers'][$i]['designer_settings'] = 'pma__designer_settings';
$cfg['Servers'][$i]['export_templates'] = 'pma__export_templates';

注意:所有表名前缀 pma__ 是 phpMyAdmin 的默认约定,不要改成 phpmyadmin_ 或其他。导入 SQL 后,用 sudo mysql -u pma_user -p phpmyadmin -e "SHOW TABLES;" 确认 17 张表全部存在。

完成这一步,用户登录后点击“设置”→“保存”,就能永久保存自己的工作区布局、常用 SQL 查询、表关系图——这才是真正可用的企业级体验,而不是每次刷新都回到初始状态。

5. 最终加固:四层防护网,让 phpMyAdmin 从“公开靶子”变成“受控仪表盘”

安装完成不等于安全。Ubuntu 18.04 的默认 Apache 配置开放了大量信息,phpMyAdmin 的默认界面又自带版本号、错误详情,这些都会成为自动化扫描器的“路标”。我们必须主动收窄攻击面。

5.1 屏蔽敏感信息输出:关闭 PHP 错误显示,隐藏 Apache 版本

编辑 Apache 主配置:

sudo nano /etc/apache2/apache2.conf

找到 <IfModule mime_module> 区块,在其后添加:

# 隐藏 Apache 版本和操作系统信息
ServerTokens Prod
ServerSignature Off

编辑 PHP 配置(Apache 模式):

sudo nano /etc/php/7.2/apache2/php.ini

修改以下两项:

display_errors = Off
expose_php = Off

重启 Apache:

sudo systemctl restart apache2

验证效果:

  • 访问一个不存在的 PHP 文件(如 http://localhost/test.php ),不再显示 Apache/2.4.29 (Ubuntu) Server at localhost Port 80
  • 故意写一个语法错误的 PHP 文件,浏览器只显示空白,而非详细的 Parse Error 堆栈。

5.2 限制访问来源:用 .htaccess 或 Apache 配置实现 IP 白名单

如果你只在公司内网使用 phpMyAdmin,强烈建议限制访问 IP。编辑 phpMyAdmin 的 Apache 配置文件:

sudo nano /etc/apache2/conf-available/phpmyadmin.conf

<Directory /usr/share/phpmyadmin> 块内,将 Require all granted 替换为:

# 只允许 192.168.1.0/24 网段访问
Require ip 192.168.1.0/24
# 如果还需允许本地回环,加上
Require ip 127.0.0.1

保存后, sudo systemctl restart apache2 。这样,任何来自公网的请求都会直接返回 403,连登录页都看不到。

5.3 启用 HTTPS 强制跳转:防止密码明文传输(即使内网也建议)

Ubuntu 18.04 自带 certbot ,申请 Let's Encrypt 免费证书只需三步:

sudo apt install certbot python3-certbot-apache
sudo certbot --apache -d your-domain.com
# 按提示选择 2:Redirect to https

Certbot 会自动修改你的 Apache 配置,添加 301 重定向规则。此后所有 HTTP 请求都会跳转到 HTTPS,密码、Cookie 全程加密。

5.4 日志审计与异常监控:把 /var/log/apache2/ 变成你的“安全哨兵”

phpMyAdmin 的访问日志是入侵检测的第一道防线。确保 Apache 启用了详细日志:

sudo nano /etc/apache2/apache2.conf

确认以下行未被注释:

LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined

然后创建一个简单的监控脚本(每天检查异常登录):

#!/bin/bash
# /usr/local/bin/check-pma-failures.sh
LOG="/var/log/apache2/access.log"
# 统计过去 24 小时内,phpmyadmin 路径的 401/403 错误次数
FAILURES=$(awk -v date="$(date -d '24 hours ago' '+%d/%b/%Y:%H:%M')" \
    '$4 > "["date"]" && $9 ~ /^(401|403)$/ && $7 ~ /phpmyadmin/' "$LOG" | wc -l)

if [ "$FAILURES" -gt 10 ]; then
    echo "$(date): Suspicious phpMyAdmin access attempts ($FAILURES)" | mail -s "ALERT: phpMyAdmin Brute Force?" admin@localhost
fi

赋予执行权限并加入 cron:

sudo chmod +x /usr/local/bin/check-pma-failures.sh
echo "0 * * * * /usr/local/bin/check-pma-failures.sh" | sudo crontab -e

这个脚本不会阻止攻击,但它会在攻击发生时立刻通知你——这才是运维的终极目标:不求万无一失,但求第一时间响应。

6. 故障排查实战:从 500 Internal Server Error 到 403 Forbidden,我的五次深夜重启记录

理论讲完,现在进入最真实的部分:我在 Ubuntu 18.04 上部署 phpMyAdmin 时,遇到的五个真实故障,以及我是如何一步步定位、验证、解决的。这些过程不会出现在任何官方文档里,但它们构成了“能用”和“稳用”之间的全部距离。

6.1 故障一:500 Internal Server Error,错误日志只显示 “PHP Parse error: syntax error”

现象:浏览器打开 http://localhost/phpmyadmin ,一片空白,Apache 错误日志里只有:

[Mon Jun 10 22:17:03.123456 2024] [php7:error] [pid 12345] [client 127.0.0.1:56789] PHP Parse error:  syntax error, unexpected '}' in /usr/share/phpmyadmin/libraries/vendor_config.php on line 123

排查链路:

  • 第一步: cd /usr/share/phpmyadmin/libraries/ && ls -la vendor_config.php —— 发现文件大小为 0,是空文件!
  • 第二步: sudo apt install --reinstall phpmyadmin —— 重装后文件恢复,但错误依旧。
  • 第三步: sudo nano /usr/share/phpmyadmin/libraries/vendor_config.php ,跳到第 123 行,发现是 } else { 后面少了一个 }
  • 根本原因:Ubuntu 的 phpmyadmin 包在 4.6.6-5ubuntu0.2 版本中, vendor_config.php 存在一个已知的语法错误(Debian Bug #928765)。

解决方案:

sudo sed -i '123s/^/}/' /usr/share/phpmyadmin/libraries/vendor_config.php

即在第 123 行开头插入一个 } 。这是上游修复前的临时补丁,比等待新包发布快得多。

6.2 故障二:登录页显示 “Cannot start session without errors”,但 session.save_path 正确

现象:输入用户名密码后,页面刷新,但始终停留在登录页,URL 变成 index.php?token=xxx ,错误日志无报错。

排查链路:

  • 第一步: php -r "echo session_save_path();" 输出 /var/lib/php/sessions
  • 第二步: ls -ld /var/lib/php/sessions —— 权限是 drwxr-xr-x root:root ,而 Apache 进程用户是 www-data ,无写入权限!
  • 第三步: sudo chown www-data:www-data /var/lib/php/sessions ,重启 Apache。

经验:Ubuntu 18.04 的 /var/lib/php/sessions 目录权限默认为 root:root ,这是为了防止多用户共享 session 目录。但单机部署时,必须显式授权给 www-data

6.3 故障三:登录成功后,点击任何数据库都报 “#1045 Cannot log in to the MySQL server”

现象:登录页能进,但一选数据库就跳回登录页,错误日志显示 mysqli_real_connect(): (HY000/1045): Access denied for user 'pma_user'@'localhost'

排查链路:

  • 第一步: sudo mysql -u pma_user -p 手动登录,成功 —— 证明用户密码正确;
  • 第二步: sudo nano /etc/phpmyadmin/config.inc.php ,检查 $cfg['Servers'][$i]['auth_type'] ,发现被误设为 config (明文模式),而非 cookie
  • 第三步: config 模式下,phpMyAdmin 会尝试用配置文件里的 user / password 直连,但我们的配置里 password 是空的。

解决方案:

  • 确保 $cfg['Servers'][$i]['auth_type'] = 'cookie';
  • 清除浏览器中所有 phpmyadmin 相关 cookie;
  • 重新登录。

6.4 故障四:导出 SQL 时,生成的文件名是 database.sql ,但下载后内容为空

现象:点击“导出”→“快速”,下载的 database.sql 文件大小为 0 字节。

排查链路:

  • 第一步: df -h /tmp —— 发现 /tmp 分区已满(100%);
  • 第二步:phpMyAdmin 导出时,先在 /tmp 生成临时文件,再流式发送给浏览器。 /tmp 满导致写入失败。

解决方案:

# 清理临时文件
sudo rm -rf /tmp/*
# 或修改 phpMyAdmin 临时目录
sudo mkdir -p /var/tmp/pma
sudo chown www-data:www-data /var/tmp/pma
sudo nano /etc/phpmyadmin/config.inc.php
# 添加:
$cfg['TempDir'] = '/var/tmp/pma';

6.5 故障五:从 Chrome 登录正常,但从 Firefox 登录后一直重定向循环

现象:Firefox 地址栏疯狂跳转 index.php?token=xxx index.php?token=yyy index.php?token=zzz ,最终超时。

排查链路:

  • 第一步: curl -v http://localhost/phpmyadmin/ ,发现响应头中有 Set-Cookie: phpMyAdmin=xxx; path=/phpmyadmin; HttpOnly; Secure
  • 第二步: Secure 标志要求 Cookie 只能通过 HTTPS 传输,但当前是 HTTP 站点;
  • 第三步:Firefox 严格遵守 RFC,拒绝接收带 Secure 的 HTTP Cookie,导致 token 无法持久化。

解决方案:

sudo nano /etc/phpmyadmin/config.inc.php
# 添加:
$cfg['CookiePath'] = '/phpmyadmin/';
$cfg['CookieSecure'] = false; // HTTP 站点必须设为 false
$cfg['CookieHttpOnly'] = true; // 保持 HttpOnly 防 XSS

这五个故障,每一个我都经历过。它们共同指向一个事实:phpMyAdmin 在 Ubuntu 18.04 上的部署,不是按部就班的流水线,而是一场与系统细节、版本兼容性、权限模型的持续对话。你不需要记住所有命令,但必须理解每个命令在解决什么问题——这才是资深博主和普通教程搬运工的根本区别。

我在实际运维中发现,最可靠的 phpMyAdmin 状态检查清单只有三行:

# 1. Apache 是否加载了 phpmyadmin 配置?
sudo apache2ctl -t -D DUMP_INCLUDES | grep phpmyadmin

# 2. PHP 扩展是否全部启用?
sudo php -m | grep -E "mysqli|mbstring|gd|zip"

# 3. MySQL 用户是否能连上?
sudo mysql -u pma_user -p'StrongP@ssw0rd2024!' -e "SELECT VERSION();"

只要这三行全部返回预期结果,你的 phpMyAdmin 就一定在正常工作。其余所有花哨功能,都是锦上添花;而这三行,才是雪中送炭的底线。

更多推荐