From 5b57e6a81e29fd27f803d23d0864f25d0ac2041e Mon Sep 17 00:00:00 2001
From: laoyang
Date: Tue, 3 Nov 2026 22:32:04 +0800
Subject: [PATCH] =?UTF-8?q?=E5=AE=89=E8=A3=85=E5=AE=8C=E6=88=90=E5=90=8E?=
=?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=88=A0=E9=99=A4=20install.php=EF=BC=88?=
=?UTF-8?q?=E4=B8=8D=E5=86=8D=E8=AE=A9=E7=94=A8=E6=88=B7=E6=89=8B=E5=8A=A8?=
=?UTF-8?q?=E5=88=A0=EF=BC=89?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
用户要求:装完由程序自己删,不该让用户记着。
三级降级(删不掉也必须安全、且如实告知):
① 目录可写 → unlink 删除
② 删不掉 → 覆写成**纯静态 HTML** 404 页(不含 true, 'mode' => 'deleted', 'msg' => '文件已不存在'];
+ }
+
+ // ① 正常删除(关键在**所在目录**是否可写,与文件自身权限无关)
+ if (@unlink($file)) {
+ return ['ok' => true, 'mode' => 'deleted', 'msg' => '已自动删除'];
+ }
+
+ // ② 删不掉 → 覆写成**纯静态 HTML**(关键:不能写成 PHP)
+ //
+ // ⚠️ 实测教训:原先写成 `\n"
+ . "404
"
+ . "
安装已完成,此文件已失效,可安全删除。
\n"; + if (@file_put_contents($file, $blank, LOCK_EX) !== false) { + // 清掉可能存在的编译缓存,让残留文件立刻按新内容(静态)生效 + if (function_exists('opcache_invalidate')) { + @opcache_invalidate($file, true); + } + return ['ok' => true, 'mode' => 'blanked', + 'msg' => '目录不可写,已覆写为无害静态页(无法执行任何代码,但仍建议手动删除)']; + } + + // ③ 彻底失败,如实上报 + $why = '未知原因'; + if (!is_writable(dirname($file))) { + $why = '目录 ' . dirname($file) . ' 不可写'; + } elseif (!is_writable($file)) { + $why = '文件本身不可写'; + } + return ['ok' => false, 'mode' => 'failed', 'msg' => '无法删除:' . $why]; +} + /* ========================================================================= * 安装状态 * ========================================================================= */ @@ -97,6 +151,7 @@ $installed = is_file($lockFile) || $hasAdmin; $err = ''; $done = false; +$delResult = null; // 自删除结果(仅安装成功那一轮有值) /* ========================================================================= * 执行安装 @@ -145,6 +200,17 @@ if (!$installed && $_SERVER['REQUEST_METHOD'] === 'POST') { } catch (Throwable $e) { $err = '安装失败:' . $e->getMessage(); } + + // 自删除**刻意放在 try/catch 之外**。 + // + // 为什么:它是一次「清理动作」,不属于安装事务。如果在 try 里抛异常, + // 会被上面 catch 兜住并写进 $err —— 而那时账号其实已经建好了, + // 等于把「清理失败」误报成「安装失败」。 + // sn_self_delete 内部全部用 @ 抑制且返回结构化结果,本身不会抛; + // 放在外面是双重保险,语义也更清楚。 + if ($done) { + $delResult = sn_self_delete(__FILE__); + } } } @@ -198,6 +264,9 @@ $title = $installed ? '已安装' : '安装向导'; .dbinfo dd{margin:0;font-variant-numeric:tabular-nums} .tip{font-size:12px;line-height:1.7;color:var(--muted,#777);margin:14px 0 0} .tip strong{color:#c62828} +.ok-tip strong{color:#128a3c} +.warn-tip strong{color:#b26a00} +.warn-tip code,.ok-tip code{background:rgba(128,128,128,.15);padding:1px 5px;border-radius:4px} @@ -245,8 +314,26 @@ $title = $installed ? '已安装' : '安装向导'; 进入后台 + + +
+ ✓ 安装文件已自动处理:= e($delResult['msg']) ?>
+ 你不需要再做任何清理。
+
+
(目录不可写所以没能物理删除,内容已清空成无害空壳;若想彻底删掉,
+ 请给站点根目录写权限后手动 rm install.php。)
+
+
+ ⚠ 安装文件没能自动删除:= e($delResult['msg']) ?>
+ 站点照常可用,但请手动执行:rm = e(APP_PATH) ?>/install.php
+ 原因通常是站点根目录对 PHP 进程不可写。
+
- 下一步(重要):把服务器上的 install.php 删掉。
后台默认已有一份示例板块和示例网站,进去之后可以随意删改、添加自己的链接。