thinkphp 6+ 日志默认存 runtime/log/、缓存存 runtime/cache/,均不自动清理旧文件;php think clear 是全量清空,非按时间筛选;需自定义命令按修改时间安全清理,并用 cron 定时执行且记录日志。

ThinkPHP 的日志和缓存文件到底存在哪?
默认情况下,ThinkPHP 6+ 的日志写在 runtime/log/,缓存(File 驱动)存在 runtime/cache/,两者都受 APP_DEBUG 和配置影响。但关键点是:这些目录不会自动清理旧文件,哪怕设置了 expire,File 缓存驱动只在读取时判断过期,不主动删磁盘文件;日志则完全按日期分文件、永不删除。
用 php think clear 能不能解决?
不能直接解决“定期清理无用文件”的需求。php think clear 是 ThinkPHP 内置命令,它清的是 runtime/ 下所有子目录(包括 cache、log、temp),属于全量清空,不是“按时间筛选旧文件”。生产环境频繁执行会丢失有效缓存、打断调试日志追踪,而且无法设定保留最近 7 天日志这种精细策略。
怎么写一个安全可控的自定义清理命令?
核心思路:不碰 runtime/ 根目录,只遍历 log/ 和 cache/,按修改时间过滤,跳过正在写入的文件(如 2024-05-20.log 当天文件),再删除。需注意三点:
- 使用
filemtime()判断而非date()字符串匹配,避免日志文件名被篡改导致误删 - 缓存文件可能带哈希后缀(如
abc123.php),不能按扩展名硬过滤,得依赖Cache::getDriver()->getCachePath()确认路径 - Linux 下要注意
opcache.revalidate_freq可能导致刚删的缓存文件仍被 PHP 进程持有,建议加clearstatcache()
示例片段(放在 app/command/ClearOldFiles.php):
public function handle()
{
$logPath = runtime_path('log');
$cachePath = cache_path();
<pre class="brush:php;toolbar:false;">$this->clearOldFiles($logPath, 7 * 86400, '/\.log$/');
$this->clearOldFiles($cachePath, 24 * 3600, '/\.php$/');}
protected function clearOldFiles(string $dir, int $maxAge, string $pattern) { if (!is_dir($dir)) return;
foreach (scandir($dir) as $file) {
$path = $dir . DIRECTORY_SEPARATOR . $file;
if (is_file($path) && preg_match($pattern, $file) && filemtime($path) < time() - $maxAge) {
@unlink($path);
}
}}
怎么让这个命令定时跑又不干扰线上服务?
Linux 下用 cron 最稳妥,但有三个坑必须避开:
- 务必用绝对路径调用 PHP 和 think 命令,比如
/usr/bin/php /var/www/tp6/think clear:old,否则 cron 环境里找不到think或扩展 - 不要在高峰期运行(如凌晨 0 点),避免大量
unlink触发磁盘 I/O 尖峰,建议设在业务低谷(如凌晨 3:22) - 加上
2>&1 >> /var/log/tp-clear.log记录实际删了哪些文件,否则出问题根本没法回溯——很多团队只写 cron 却忘了留痕
真正麻烦的不是写命令,而是确认「哪些文件算无用」:日志要留多少天、缓存是否被外部系统依赖、有没有自定义缓存路径没被扫到……这些得翻 config/cache.php 和 config/log.php 逐项对齐,不能想当然。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











