应使用独立定时任务清理音频文件,每6小时执行一次,通过时间戳与数据库状态双校验确定待删文件,删除前记录日志并清除APCu及Nginx文件缓存。

PHP上传音频后不清理会撑爆磁盘
PHP处理音频上传时,如果只存不删,临时文件或用户上传的原始音频很快占满磁盘。关键不是“能不能删”,而是“什么时候删、删哪些、删之前要不要校验”。定时清理必须避开上传中、转码中、正在播放的文件,否则会出 file not found 或中断服务。
用系统crontab + PHP脚本最稳,别信“upload_cleanup() 放在 upload.php 末尾”
把清理逻辑塞进上传流程里,看似省事,实则危险:用户上传大音频(比如100MB+)时脚本超时,unlink() 根本没执行;或者并发上传时多个进程同时扫目录,可能误删刚写完一半的文件。真要可靠,得交给独立定时任务:
- 写一个专用清理脚本,比如
/var/www/cleanup_audio.php,只做一件事:扫描/var/www/uploads/audio/下超过24小时且无数据库记录的.mp3、.wav、.m4a文件 - 在 crontab 里加一行:
0 */6 * * * /usr/bin/php /var/www/cleanup_audio.php >> /var/log/audio_cleanup.log 2>&1(每6小时跑一次) - 脚本开头加
ignore_user_abort(true); set_time_limit(0);,防止因HTTP连接断开中断清理
判断“可删”的核心是时间戳 + 数据库状态双校验
只看文件修改时间(filemtime())不可靠——上传中途失败的文件、调试时手动放进去的测试文件,都可能被误杀。必须结合业务状态:
- 查数据库表
audio_files,找出所有status = 'processed'且updated_at < NOW() - INTERVAL 1 DAY的file_path - 再用
scandir()扫描上传目录,对每个音频文件检查:!in_array($file, $db_paths)且time() - filemtime($full_path) > 86400 - 删除前加日志:
error_log("Deleting stale audio: {$full_path} (mtime: " . date('Y-m-d H:i', filemtime($full_path)) . ")\n", 3, '/var/log/audio_cleanup.log'); - 用
unlink()删除,别用exec('rm')—— 权限和路径空格容易出错
注意opcache和APCu缓存导致的“删了但还显示”问题
有些项目用 apcu_store() 缓存了音频元数据,文件物理删了,但缓存里还留着旧路径,前端请求时仍返回404或500。清理脚本末尾务必补上:
立即学习“PHP免费学习笔记(深入)”;
apcu_clear_cache(); // 清全量(开发环境够用)
// 或更精准:
apcu_delete('audio_meta_' . md5($file));另外,Nginx 的 open_file_cache 可能缓存已删除文件的句柄,重启不现实,可在清理后加 kill -s USR1 `cat /var/run/nginx.pid` 重载缓存(仅限Nginx配置启用了该特性)。
真正麻烦的是音频转码队列里的待处理文件——它们既不在数据库记录里,又不能按时间硬删。这类必须单独建 pending_jobs 表跟踪,清理脚本要先查队列表,再决定是否跳过。



















