
接手一个装到一半的站点最让人头疼的不是报错而是报错只给你一句话请确认当前目录是否有写入权限。微擎安装过程中这句提示几乎是每个新手都要撞一次的墙——它不告诉你哪个目录、不告诉你是谁在写、也不告诉你是权限不足还是环境不对。我处理过的这类求助里真正因为chmod少给了权限的占不到四成剩下的六成是属主错了、上层策略拦截、磁盘写满、挂载变只读、旧安装残留没清干净。所以这篇不打算只丢一句chmod -R 777就收工而是把这句提示背后的判断链条摊开讲微擎到底要往哪些目录写字、PHP 进程是以什么身份在写、为什么你在命令行里看着明明有权限它还是报错以及整套安装流程里哪些步骤决定了后面会不会反复翻车。内容偏实操适合自己动手搭过 PHP 站点、但对 Linux 权限模型还不太有把握的朋友也适合已经把站点装完、结果隔三差五冒出权限类报错的人回头对照排查。1. 这句报错到底卡在哪一步把提示拆成可验证的假设先把这句中文提示还原成技术语言。微擎安装程序在真正执行安装动作之前会做一次前置检查核心判断大致是is_writable()一类函数对若干目标路径的返回值。返回 false它就把这句提示抛出来。注意这里的措辞是当前目录实际上它检查的往往不止一个目录而是配置文件所在目录、缓存目录、附件目录等一组路径。所以看到这句话第一反应不应该是给根目录加权限而是它到底在检查哪几个路径。判断依据是什么安装程序要落地的东西包括数据库连接配置文件、安装锁文件、运行时缓存、模板编译产物。这四类文件分散在不同目录里任何一处不可写整个流程都会停。而提示文案为了通用把它们统称为当前目录于是就有了误导。1.1 报错出现的三个典型时机与各自指向同一个提示在不同阶段出现指向的问题完全不同。我一般先问对方这个提示是在点下一步之前出现还是提交表单之后出现还是进入安装界面之前就白了出现时机大概率指向判断依据打开安装入口页就报安装目录本身或入口文件不可读、路径解析异常页面能打开但内容异常或直接输出提示填写数据库信息后报配置写入目录不可写、磁盘满、挂载只读表单提交后回跳无进一步报错安装进度条中途报缓存目录、附件目录不可写或模块目录缺失进度卡在某个百分比第一种情况其实很少见因为安装入口页是纯读取只要文件在、PHP 能解析就出不来这句话。真遇到了多半是路径被重写规则劫持了或者站点根目录设置错了一层导致安装程序找到的当前目录压根不是你想象的那个目录。第二种情况最常见。用户填完数据库账号密码点提交页面弹回来一句请确认当前目录是否有写入权限。这时候安装程序正在尝试把配置写进data目录下的配置文件。它写不进去就只能回退到安装页并抛出提示。真正的原因可能是目录属主不对也可能是磁盘配额满了还可能是这台机器上跑了某种强制访问控制策略把写动作拦下来了。第三种情况容易被忽略。进度条走到一半停住提示写入失败是因为前面几步只是写配置写配置文件这个动作本身权限要求不高一般是覆盖单个文件而到了生成缓存、释放模块包、创建附件目录这一步涉及大量新建文件和子目录对目录权限的要求就上来了——不仅要能写还要能在里面创建新条目也就是目录需要w和x两个位同时具备。很多人只给了w忘了x或者用chmod 666给目录加了写权限结果照样失败因为目录没有执行位就无法进入、无法创建条目。提示给目录授权时x执行位在目录上的含义是可进入、可作为路径的一部分被访问不是可执行程序。目录缺x时即使有w也无法在其中创建文件。这是新手最常混淆的一点。1.2 PHP 进程身份与文件属主的错位这是所有权限问题的根。你在 SSH 里敲命令身份是root或某个普通用户而站点跑起来时PHP 进程的身份是另一套常见的是www、www-data、nginx、apache或者面板自建的账号。两套身份对同一个目录的权限判断结果可以完全相反。举个具体的例子。你用 root 登录cd到站点目录touch test.txt成功了于是你觉得这个目录可以写。但安装程序不是以 root 身份跑的它是以www身份跑的。而www对这个目录可能只有r-x没有w。你的测试和它的测试测的根本不是同一件事。验证方法很简单先确认 PHP 进程的真实身份。不同的运行方式命令不一样# 查看 php-fpm 工作进程的属主 ps -eo user,pid,cmd | grep php-fpm: pool | grep -v grep # 如果是 Apache 模块方式运行 ps -eo user,pid,cmd | grep httpd | grep -v grep # 直接问 PHP 自己推荐最准确 php -r echo get_current_user(), PHP_EOL;最后那条命令要注意如果你是在命令行里执行php它返回的是当前 shell 用户不是 web 进程的用户。想拿到 web 进程的真实身份得通过一个临时脚本在浏览器里访问或者直接查进程列表。这个区别很多人栽过跟头——明明看到输出是 root结果 web 端还是没权限。拿到身份之后再去看目录属主ls -ld /path/to/site /path/to/site/data /path/to/site/attachment输出形如drwxr-xr-x 5 www www 4096 ...第三列是属主第四列是属组。如果属主是 root而 PHP 进程是 www那么目录的rwx只对 root 生效www 只能享受其他用户那一组权限——通常是r-x写不进去。1.3 本地能装、服务器报错的差异来源这个对比几乎每周都有人问。本机用集成环境一键装顺顺利利传到服务器上就卡在权限提示。差异来自三处第一集成环境为了省事通常让 web 进程以当前登录用户身份运行甚至直接以管理员身份运行权限天然对齐。服务器上是分离的进程身份和你登录的身份是两回事。第二集成环境的站点目录一般放在用户主目录下文件系统是普通本地盘。服务器上可能是挂载的网络存储、容器卷、或者带有配额限制的分区写行为受额外约束。第三服务器上多了安全策略层。某些发行版默认开启强制访问控制它对文件写入的判定独立于传统的rwx位。你把权限改成 777看着已经不能再开放了策略层照样拒绝日志里留下一行拒绝记录而应用层只看到写失败。这一类问题最耗时间因为传统排查思路在这里完全失效。2. 装之前先对地基微擎跑起来需要的目录与依赖清单很多人装微擎的顺序是上传、访问、报错、改权限、再报错、上网搜。这个循环能走出来但很累。更省事的做法是装之前花十分钟把地基对一遍把能提前发现的问题提前解决掉。2.1 PHP 版本与扩展的硬性核对微擎不同分支对 PHP 版本的要求不一样老分支在 PHP 5.6 到 7.x 区间跑得比较稳新一些的分支才开始拥抱 7.4 以上。选版本的原则是跟着你拿到的安装包走不要先装个最新版 PHP 再去找包那样很容易撞上兼容问题——典型表现是安装页直接空白或者 500连那句权限提示都看不到。扩展方面下面这些是必须有的缺了会在安装或运行的不同阶段给你脸色看扩展作用缺失时的典型表现mysqli 或 pdo_mysql连接数据库安装第二步报数据库连接失败gd图片处理、验证码后台验证码显示为破图curl外部接口调用后台某些功能一直转圈openssl加密通信支付、推送类功能异常mbstring多字节字符串处理中文乱码、截断报错fileinfo上传文件类型识别上传附件失败或类型判断错误zip解压模块包后台装模块时解压失败核对命令php -m | grep -Ei mysqli|pdo_mysql|gd|curl|openssl|mbstring|fileinfo|zip注意这里查的是命令行 PHP 的扩展列表和 web 端加载的扩展可能不是同一份配置。更可靠的方式是在站点根目录丢一个临时文件内容只有一行?php phpinfo();浏览器访问看Loaded Configuration File指向哪个 ini再看扩展是否加载。用完立刻删掉这东西暴露的信息太多。顺带提一句disable_functions。部分环境为了安全把一批函数禁掉了其中可能包括与文件操作、目录遍历相关的函数。安装程序调用被禁用的函数时返回值可能是 false于是它按照写失败的逻辑抛出那句权限提示。这种情况你查权限查一整天都查不出来因为权限根本没问题是函数被掐了。所以核对清单里要加一条看一眼禁用函数列表里有没有跟文件系统相关的条目。2.2 目录规划哪些路径必须可写微擎的目录结构大致分两类一类是框架代码和入口文件装完之后基本不动不需要写权限另一类是运行时产物必须可写。分清楚这两类才能做到该开的地方开不该开的地方坚决不开。需要写权限的典型路径配置与缓存所在的数据目录安装时写数据库连接信息运行时写缓存文件和编译产物附件目录用户上传的图片、文档落在这里还要按日期自动建子目录模块/插件目录后台在线安装或上传模块包时往这里解压安装目录本身安装过程要写锁文件装完就该删掉或改名。不需要写权限的路径框架核心代码目录、静态资源目录、入口文件所在层。这些地方给了写权限纯属给自己埋雷——万一哪天有个上传漏洞攻击者能往可执行目录里塞文件后果比只读严重得多。判断某个路径在不在必须可写的名单里有个笨但有效的办法安装报错时把它提示的路径和上面这份清单对一遍如果对不上说明它想写的东西超出了常规范围这时要警惕是不是路径配置本身出了问题比如站点根目录设错了一层导致它把上层目录当成了自己的家。2.3 数据库与站点配置的前置准备安装之前先把数据库建好不要指望安装程序帮你建库。原因有两个一是安装程序建库需要更高的数据库权限很多生产环境不给二是建库时的字符集如果没指定可能落成非 utf8mb4后面存表情符号或四字节字符会出问题。建库语句建议明确指定字符集CREATE DATABASE we7_demo DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE USER we7_userlocalhost IDENTIFIED BY 换成强密码; GRANT ALL PRIVILEGES ON we7_demo.* TO we7_userlocalhost; FLUSH PRIVILEGES;站点配置这边要确认三件事域名解析是否已经生效、站点根目录是否指向了安装包解压后的那一层不是它的上一层也不是它的子目录、伪静态规则是否已经准备好。根目录指错一层是访问安装页却提示找不到文件或者权限提示反复出现的常见原因——因为安装程序算出来的相对路径全部偏移了一级。3. 一次装通的完整流程从上传到进入后台把地基对完之后正式安装其实很快。我把顺序理成一条线照着走基本不会回头。3.1 上传解压与文件属主的第一次修正安装包上传到服务器后建议先在临时目录解压再整体移动到目标位置而不是直接往站点根目录里解压覆盖。这样做的理由是避免残留文件如果你之前装过一次没成功根目录里可能躺着一份半成品配置和缓存新包覆盖上去之后新旧混在一起安装程序读到的状态是混乱的。移动完成后的第一件事不是访问是修属主# 假设站点目录是 /www/wwwroot/demo cd /www/wwwroot chown -R www:www demo把www:www换成你环境里真实的 web 进程用户和组。这一步做完绝大部分写入权限报错就已经消失了因为问题从来不是权限位不够而是属主不对。接着统一权限基线cd /www/wwwroot/demo find . -type d -exec chmod 755 {} \; find . -type f -exec chmod 644 {} \;目录 755、文件 644这是绝大多数 PHP 站点的通用基线属主可读写执行同组和其他用户可读可执行但不可写。之后只需要给少数几个目录额外加写权限即可不用全站放开。3.2 授权方式的选择chmod、chown、ACL 怎么选三种手段解决的是不同层面的问题混用会互相打架。chown改的是这个文件归谁属于所有权层面的调整。它是最干净的解法把目录交给 web 进程用户之后这个用户对它就有完整权限不需要把权限位开到 777 让所有人都有份。chmod改的是权限位属于访问控制层面的调整。它的副作用是面向所有匹配的用户生效777意味着机器上任何一个账号都能改你的站点文件这在共享环境里是很危险的。setfacl是第三种选择它能在不改属主的前提下单独给某个用户或组授权。适合那种多个服务共用同一份目录的场景。我一般的取舍是能改属主就改属主改不了再用 ACL最后才考虑放宽权限位。只有一种情况我会临时用 777 做验证——快速确认到底是不是权限问题验证完立刻改回去。把 777 留在生产环境等于给自己留了个不知道什么时候会响的雷。如果确实要用 ACL命令大致是# 递归授予 www 用户对 data 目录的读写进入权限 setfacl -R -m u:www:rwx /www/wwwroot/demo/data # 让新建的子文件继承同样的 ACL setfacl -R -d -m u:www:rwx /www/wwwroot/demo/data第二条的-d是默认 ACL作用是新创建的文件自动继承不做这一步的话运行时新建的缓存文件又会被打回默认权限于是报错在跑了一段时间之后重新出现。3.3 安装向导每一步该填什么访问站点域名正常情况下会跳到安装入口。整个向导大概四步每步都有坑。第一步通常是环境检测会列出一堆目录和扩展的检查结果。这一步要一个格子一个格子看别看个大概就往下点。凡是有红色标记的先解决再继续。这里的检查结果和后面那句写入权限提示是强相关的——如果这一步显示某目录不可写你硬着头皮点下一步后面必然失败。第二步填数据库信息。主机地址这一栏本地数据库填localhost或127.0.0.1如果数据库在另一台机器上填内网地址同时确认对方允许远程连接、防火墙放行了端口。有个细节填localhost时部分环境会走 Unix socket 而不是 TCP此时如果 socket 路径不对会报连接失败但端口是通的。搞不清楚就用127.0.0.1强制走 TCP行为更可预期。表前缀建议改掉默认值。不是为了安全虽然也有一点用主要是避免同一个库里装多个应用时表名冲突。前缀用三到四个字母加下划线别用纯数字开头。第三步填管理员账号密码。这里没什么技巧就是别用弱密码账号名别用默认的。装完之后第一时间确认这个账号能正常登录后台。第四步是执行安装会跑一段进度。这一段如果卡住或者报错回到第 1 节的三时机表对照定位。3.4 装完必做的四件收尾事安装成功不等于装好了。下面四件事不做后面迟早出问题。第一件删掉或重命名安装目录。安装程序很多是幂等的留着它意味着任何人都能重新触发安装流程覆盖你的配置。直接删除是最省事的如果担心以后要重装把它改名成带随机后缀的形式。第二件把不该开写的目录权限收回来。安装过程中为了省事可能放宽过某些目录装完要改回去。参见第 5 节的基线表。第三件检查配置文件的实际属主。安装程序写入的配置文件属主可能是 web 进程用户这没问题但如果它被写成了 root 属主而权限是 644那么后续后台修改配置时会写不进去。看一眼ls -l确认一下。第四件打开调试开关跑一遍首页。新装的站点开着调试模式访问一遍前后台能把隐藏的警告和通知暴露出来比如某个扩展缺失、某个目录不可写但只在特定页面触发。确认没问题后再把调试关掉。4. 权限明明给足了还报错完整排查链路这是最有价值的一节因为九成的求助都卡在这里。你的操作没错但问题在别处。下面是我实际用的一套排查顺序从下往上一层一层排除。4.1 从文件系统往上逐层验证先确认最底层的事实路径对不对、磁盘满不满、挂载是不是只读。路径核对。安装程序眼里的当前目录可能和你以为的不是同一个。用一个临时脚本把真实路径打出来?php echo 脚本所在目录: , __DIR__, PHP_EOL; echo 站点根目录: , $_SERVER[DOCUMENT_ROOT] ?? 未设置, PHP_EOL; echo 进程用户: , get_current_user(), PHP_EOL; $target __DIR__ . /data; echo 目标目录: , $target, PHP_EOL; echo 是否存在: , is_dir($target) ? 是 : 否, PHP_EOL; echo 是否可写: , is_writable($target) ? 是 : 否, PHP_EOL;把这个文件临时放到站点根目录浏览器访问一次然后把所有输出抄下来。很多谜题在这一步就解开了——你会发现它检查的目录和你想的不是同一个或者进程用户根本不是你以为的那个。磁盘空间与 inode。磁盘写满时写操作失败应用层看到的就是不可写。df -h df -idf -h看容量df -i看 inode 数量。有一种情况是容量还剩很多但 inode 用完了——大量小文件把索引节点耗光新建文件的动作直接失败报错和权限不足一模一样。挂载状态。如果站点目录挂在网络存储或容器卷上要确认它不是只读挂载mount | grep -E ro,|\(ro有ro标记说明是只读这种情况下改多少权限都没用得先解决挂载方式。另外网络存储还有个坑客户端看到的权限和实际生效的权限可能不一致服务端的映射规则比如把 root 映射成匿名用户会让你的chown完全失效。这类问题排查起来要有耐心先在一台本地盘的机器上验证同样的包能不能装能装就说明是存储层的问题。逐级路径可达性。有时候目录本身权限没问题但它的某一级父目录缺x导致路径走不通namei -l /www/wwwroot/demo/data/config这条命令会把路径上每一级的权限都列出来哪一级断了一眼就能看到。这个工具我极其推荐比一层层ls快得多。4.2 四类隐蔽原因与验证命令上面那层排查完还是不行就看下面四类。它们共同的特点是传统ls -l看起来一切正常。第一类强制访问控制策略拦截。部分发行版默认开启它对文件访问有一套独立于rwx的规则。验证方法getenforce返回Enforcing说明在生效。临时切到宽容模式做验证setenforce 0如果切完之后立刻能写了基本可以确认是它。生产环境不要长期关着正确的做法是给站点目录打上允许 web 进程写入的标签chcon -R -t httpd_sys_rw_content_t /www/wwwroot/demo/data chcon -R -t httpd_sys_rw_content_t /www/wwwroot/demo/attachment注意打完标签之后如果目录内容有变动比如重新解压了安装包标签可能会被重置需要重新打一遍。这是很多人明明配好了重装又不行的原因。第二类面板或运行环境的路径限制。不少一键环境会在 PHP 配置里加一条路径白名单限制脚本只能访问指定目录树。如果安装程序试图访问白名单之外的路径比如把临时文件写到系统临时目录就会被拦下来返回值同样是失败php -i | grep -i open_basedir如果输出里有一串路径检查你的站点目录在不在里面。不在就补进去注意分隔符和结尾斜杠的写法。第三类上层缓存或残留文件。上一次安装失败留下的锁文件、旧配置文件、编译缓存会让新安装读到错误的状态。表现是权限明明改了还是同样的提示。清理方式是找到这些残留删掉重来# 谨慎操作先确认内容再删 ls -la /www/wwwroot/demo/data/看到形如安装锁、旧配置、缓存目录的东西先备份再删。这一步我做过的次数最多也是最容易见效的。第四类容器或虚拟化环境的映射问题。容器里跑 PHP宿主机上的文件通过卷映射进来。容器内的用户 ID 和宿主机上的用户 ID 是两个体系容器内www的 uid 可能是 33宿主机上对应的是完全不相干的账号。于是你在宿主机上chown www:www容器内看到的属主却是个陌生数字。解决办法是统一 uid查容器内进程的 uid在宿主机上把目录属主改成同一个数字。# 容器内 id www # 宿主机上按数字改属主 chown -R 33:33 /host/path/demo4.3 用临时探针脚本定位真实失败点当所有常规手段都失效时最有效的办法是让程序自己说话。写一个探针脚本把每个关键路径的判断结果全打出来一次性看清全貌?php header(Content-Type: text/plain; charsetutf-8); $paths [ __DIR__, __DIR__ . /data, __DIR__ . /attachment, __DIR__ . /addons, sys_get_temp_dir(), ]; echo 进程用户: , get_current_user(), PHP_EOL; echo 进程 uid: , function_exists(posix_geteuid) ? posix_geteuid() : N/A, PHP_EOL; echo 磁盘剩余: , disk_free_space(__DIR__) ?: 读取失败, PHP_EOL; echo str_repeat(-, 40), PHP_EOL; foreach ($paths as $p) { printf( %-50s 存在:%s 可写:%s 权限:%s\n, $p, is_dir($p) ? Y : N, is_writable($p) ? Y : N, is_dir($p) ? substr(sprintf(%o, fileperms($p)), -4) : - ); }最后一个sys_get_temp_dir()特别值得关注。安装程序在上传文件、解压模块时往往先把内容放到系统临时目录再移动。如果临时目录不可写报错信息一样会指向写入权限但你去改站点目录的权限改到天亮也没用。这个点非常隐蔽我见过至少三次因为临时目录权限问题导致安装失败、排查了大半天的案例。用完记得删掉这个文件它暴露的信息比你想象的多。5. 装好之后把口子收回来权限收敛与长期维护安装阶段为了顺利推进权限普遍给得比较宽。装完不收等于把门敞着。这一节给一份可以照着执行的基线。5.1 各目录的最终权限基线路径类型属主目录权限文件权限说明站点根目录web 用户755644常规基线不放开写框架核心代码root755644只读防止被篡改数据/缓存目录web 用户755644需可写靠属主解决而非放开权限位附件上传目录web 用户755644同上禁止执行脚本模块目录web 用户755644后台在线安装时需要写配置文件web 用户-600含数据库密码越小越好安装目录删除或改名--装完必须处理有一点要特别强调附件目录必须禁止脚本执行。用户上传的文件里可能混入伪装成图片的脚本如果这个目录允许解析就等于开了一个上传入口。做法有两种一是在该目录下放一个限制规则文件二是在站点配置里单独对这个路径关掉脚本解析。前者更通用# 在附件目录下放置限制规则Nginx 环境下需配合配置 printf location ~* \\.(php|php5|phtml)$ { deny all; }\n /www/wwwroot/demo/attachment/.htaccess这个是权宜之计最稳妥的还是直接在 web 服务器配置里针对这个路径段写一条拒绝规则避免依赖目录级配置是否被加载。5.2 上传文件归属错乱的连锁反应一个很典型的现象站点跑了一段时间后台突然传不了图日志里全是权限拒绝。根因往往是历史遗留问题——早期安装时用 root 跑过一次命令行脚本生成的缓存文件属主成了 root之后 web 进程想覆盖这些文件写不进去。这类问题的诊断思路是找属主异常的文件# 找出属主不是 www 的文件把 www 换成实际用户 find /www/wwwroot/demo -not -user www -ls | head -50如果输出里有大量文件说明历史上确实混用过身份。批量修正chown -R www:www /www/wwwroot/demo/data chown -R www:www /www/wwwroot/demo/attachment修正完再观察一段时间。如果又出现新的异常文件说明有某个定时任务或后台进程还在用错误身份执行得从源头改。预防的办法很简单所有涉及站点的命令行操作统一用 web 用户身份执行需要提权的场景用切换用户的方式跑sudo -u www php /www/wwwroot/demo/some-script.php这样生成的文件属主天然正确不用事后补救。5.3 日常巡检清单权限类问题不会一次性解决完就永远消失环境变动、程序升级、迁移服务器都可能让配置失效。我习惯在下面这些节点做一次快速巡检迁移服务器之后重新核对属主和权限基线重点看配置文件程序升级之后检查升级过程是否新建了目录新目录是否带了正确属主装完新模块之后检查模块目录里是否有属主异常的文件每隔一段时间抽查一次日志看有没有持续的权限拒绝记录。巡检命令可以攒成一条跑一遍看结果SITE/www/wwwroot/demo echo --- 属主异常文件 --- find $SITE -not -user www -type f | head -20 echo --- 全局可写文件应为空--- find $SITE -type f -perm -ow | head -20 echo --- 全局可写目录应为空--- find $SITE -type d -perm -ow | head -20 echo --- 磁盘与 inode --- df -h $SITE; df -i $SITE第二、三条是我最看重的。全局可写意味着任何账号都能改你的文件这在多用户环境下是实打实的风险。正常情况下这两条的输出应该是空的如果冒出来内容逐个确认是不是安装阶段遗留的。6. 几个高频连带问题500、白屏、数据库连不上权限问题解决之后紧接着大概率会撞上下面这几个。它们的表象和权限问题很像但原因完全不同。6.1 安装页 500 与空白页页面直接 500 或者一片空白说明 PHP 在解析阶段就挂了还没走到业务逻辑所以连那句权限提示都看不到。排查顺序是先看 web 服务器的错误日志再看 PHP 的错误日志。日志路径各处不同可以从配置文件里找error_log这一项或者用php -i | grep error_log查。最常见的原因是 PHP 版本不匹配。安装包里的代码用了新版本才支持的语法跑在老版本上直接解析失败。表现就是白屏加一行语法错误日志。这种情况换版本比改代码现实得多。第二常见的是扩展缺失导致的致命错误比如调用了某个不存在的函数。日志里会明确写出函数名对着名字装扩展就行。第三是文件权限过于严格导致读不了。注意这次是读不了不是写不了——如果入口文件的权限被设成了 600 且属主是 rootweb 进程读不到它同样报 500。这种情况在为了安全把权限收得太狠的场景里出现过。6.2 数据库连接失败的几种表现数据库连不上报错信息有时很含糊只说连接失败。按下面顺序对表现可能原因验证方式立即失败无延迟账号密码错、库不存在、主机地址错用命令行客户端连一次等待数秒后超时网络不通、防火墙拦截、对方未监听telnet 主机 端口或nc -vz提示权限不足账号没有该库的访问权查账号授权表时好时坏连接数打满、连接池配置不当看数据库的当前连接数与上限命令行验证是最快的mysql -h 127.0.0.1 -P 3306 -u we7_user -p we7_demo -e SELECT 1;能连上说明数据库侧没问题问题在应用配置连不上说明是环境侧的问题先解决它。有个细节值得单独提如果主机地址填的是localhost客户端会优先走 Unix socket。而 web 进程和你在命令行里用的 socket 路径可能不一致不同版本、不同安装方式导致命令行走得通、web 走不通。这种情况改成127.0.0.1强制走 TCP问题立刻消失。我遇到过好几次改一个地址省下半天的排查。6.3 伪静态与入口文件配置装完之后后台能进但前台页面 404大概率是伪静态没配。这类问题的特征是带参数的动态地址能访问美化后的静态地址访问不了。解决方式是把对应的重写规则加到站点配置里规则内容跟着程序提供的模板走不要自己瞎写。配置完之后有个坑规则生效需要重载配置但有时候重载不生效是因为配置文件语法有误被忽略加载了。改完配置一定先做一次语法检查再重载。检查命令依环境不同多数是nginx -t一类。还有入口文件被误删的情况。有人清理目录时手抖删了入口文件然后访问一片空白还以为是权限问题。这种时候先ls看一眼文件在不在比查权限快得多。最后分享一个我个人习惯每装完一个站点把本次用到的权限配置、属主设置、扩展清单记成一份简短的环境备注和站点放在一起。下次迁移或者排查的时候直接对照备注恢复能省掉大量当时到底是怎么配的的回忆时间。尤其是那种一年才动一次的站点没有备注基本等于从零开始。