sys_get_temp_dir() 返回的目录需确保可写、路径准确且自动清理:先查真实路径(tmpdir→php.ini→系统默认),再验权限,用tmpfile()或register_shutdown_function兜底清理。

PHP 的 sys_get_temp_dir() 返回的目录,不是“拿来就能写”的安全区——权限不对会 Permission denied,不清理会 inode 耗尽、磁盘告警、甚至 Cannot allocate memory(尤其在 /dev/shm 这类内存临时目录中)。关键不在“清不清”,而在“谁在用、能不能写、怎么收尾”。
查清真实临时目录在哪,别只盯 /tmp
PHP 按顺序查找临时目录:环境变量 TMPDIR → php.ini 中 sys_temp_dir → upload_tmp_dir → 系统默认(如 /tmp 或 C:\Windows\Temp)。只清 /tmp 可能完全没动到实际路径。
- 运行命令确认真实路径:
php -i | grep -E 'sys_temp_dir|upload_tmp_dir|TMPDIR' - 若输出中
sys_temp_dir为空,说明 PHP 正 fallback 到系统默认路径;若upload_tmp_dir是/var/www/tmp,那/tmp再大也和上传失败无关 - Docker 环境中常见
TMPDIR=/dev/shm,这是内存挂载点,满了报 “Cannot allocate memory”,不是磁盘满
目录权限必须可写,且注意跨平台与安全策略
即使路径正确,权限不足也会直接失败。Linux 下 /tmp 默认是 1777(带 sticky bit),但某些加固服务器会改成 750,导致 www-data 或 nginx 用户无法写入。
- 代码中应主动检查:
if (!is_writable(sys_get_temp_dir())) { throw new Exception('临时目录不可写'); } - 确保目录存在、属主为 Web 用户(如
chown www-data:www-data /var/tmp/php)、权限合理(如chmod 755 /var/tmp/php) - SELinux/AppArmor 可能拦截写入,
ls -Z查上下文,必要时用chcon -t httpd_tmp_t修正 - 避免硬编码路径,始终用
sys_get_temp_dir() . DIRECTORY_SEPARATOR . uniqid()
自动清理不能靠运气,得靠机制
临时文件滞留,90% 是因为异常退出跳过了 unlink(),或用了 tempnam() 却没配兜底逻辑。别依赖系统定时清理——有些系统根本不清理。
- 优先用
tmpfile():返回资源句柄,脚本结束自动释放,不用手动删 - 若必须用
tempnam(),配合register_shutdown_function()做兜底:register_shutdown_function(function() use ($tmpFile) { if (file_exists($tmpFile)) unlink($tmpFile); }); - 清理前先确认无活跃句柄占用:
lsof +L1 | grep php—— 显示DEL状态的文件正被进程持有,直接删不释放空间 - Composer 构建残留(如
/tmp/composer_*.zip)需单独处理,它们不走 PHP 文件操作流程,得定期扫描清理
推荐配置与实践组合
治本方式是把路径、权限、清理三者绑定成标准动作。
- 在
php.ini显式设置:sys_temp_dir = /var/tmp/php(确保该目录已创建并赋权) - 所有临时文件操作封装成函数,内部自动注册 shutdown 清理回调
- 上线前加检查脚本:
① 验证sys_get_temp_dir()是否可写
② 扫描该目录下超过 1 小时的php*、composer_*文件并告警 - CI/CD 流程中,
composer install后加一行清理:find $(php -r "echo sys_get_temp_dir();") -name 'composer_*.zip' -mmin +5 -delete 2>/dev/null
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











