PHP disk_free_space() 函数
说明: disk_free_space() 函数返回指定目录所在磁盘分区的可用空间(以字节为单位)。
语法
float|false disk_free_space ( string $directory )
参数说明
| 参数 |
描述 |
必需 |
| directory |
文件系统目录或磁盘分区 可以是绝对路径或相对路径 |
是 |
返回值
- 成功时返回可用空间的字节数(浮点数)
- 失败时返回
FALSE
注意事项
- Windows系统上,参数可以是盘符(如:"C:")或目录
- Unix/Linux系统上,参数必须是挂载点的目录路径
- 返回的是可用空间的字节数,可能需要转换为其他单位
- 结果受文件系统缓存影响,可能不是实时精确值
- 需要相应目录的读取权限
- 对于某些网络文件系统或特殊设备,可能无法获取准确信息
字节单位转换
| 单位 |
缩写 |
字节数 |
示例 |
| 字节 |
B |
1 |
1024 B |
| 千字节 |
KB |
1,024 |
1.5 KB |
| 兆字节 |
MB |
1,048,576 |
256 MB |
| 吉字节 |
GB |
1,073,741,824 |
5.2 GB |
| 太字节 |
TB |
1,099,511,627,776 |
1.8 TB |
示例
示例 1:基本使用
<?php
// 获取当前目录所在磁盘的可用空间
$directory = ".";
$free_space = disk_free_space($directory);
if ($free_space !== false) {
echo "当前目录所在磁盘的可用空间: " . $free_space . " 字节\n";
echo "可用空间: " . round($free_space / 1024 / 1024, 2) . " MB";
} else {
echo "无法获取磁盘空间信息";
}
?>
示例 2:字节单位转换函数
<?php
/**
* 将字节转换为易读的格式
*/
function format_bytes($bytes, $precision = 2) {
$units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
if ($bytes == 0) {
return '0 B';
}
$bytes = abs($bytes);
$base = log($bytes, 1024);
$floor = floor($base);
// 防止索引超出数组范围
$unit_index = min($floor, count($units) - 1);
return round(pow(1024, $base - $unit_index), $precision) . ' ' . $units[$unit_index];
}
/**
* 获取磁盘空间的详细信息
*/
function get_disk_info($directory) {
$free_space = disk_free_space($directory);
$total_space = disk_total_space($directory);
if ($free_space === false || $total_space === false) {
return false;
}
$used_space = $total_space - $free_space;
$usage_percentage = ($used_space / $total_space) * 100;
return [
'total' => $total_space,
'free' => $free_space,
'used' => $used_space,
'usage_percentage' => $usage_percentage,
'formatted' => [
'total' => format_bytes($total_space),
'free' => format_bytes($free_space),
'used' => format_bytes($used_space),
'usage_percentage' => round($usage_percentage, 2) . '%'
]
];
}
// 使用示例
$disk_info = get_disk_info("/");
if ($disk_info) {
echo "磁盘空间信息:\n";
echo "总空间: " . $disk_info['formatted']['total'] . "\n";
echo "已用空间: " . $disk_info['formatted']['used'] . "\n";
echo "可用空间: " . $disk_info['formatted']['free'] . "\n";
echo "使用率: " . $disk_info['formatted']['usage_percentage'];
} else {
echo "无法获取磁盘信息";
}
?>
示例 3:监控磁盘使用率
<?php
/**
* 磁盘监控类
*/
class DiskMonitor {
private $directories;
private $threshold;
public function __construct($directories = null, $threshold = 90) {
$this->directories = $directories ?: [
'/' => '根目录',
'/var' => '变量目录',
'/home' => '用户目录',
'/tmp' => '临时目录'
];
$this->threshold = $threshold;
}
/**
* 获取所有监控目录的磁盘使用情况
*/
public function getDiskUsage() {
$results = [];
foreach ($this->directories as $path => $label) {
$free = disk_free_space($path);
$total = disk_total_space($path);
if ($free === false || $total === false) {
$results[$path] = [
'label' => $label,
'status' => 'error',
'message' => '无法访问'
];
continue;
}
$used = $total - $free;
$usage_percentage = ($used / $total) * 100;
$results[$path] = [
'label' => $label,
'path' => $path,
'total' => $total,
'used' => $used,
'free' => $free,
'usage_percentage' => $usage_percentage,
'status' => $usage_percentage > $this->threshold ? 'warning' : 'normal',
'formatted' => [
'total' => $this->formatBytes($total),
'used' => $this->formatBytes($used),
'free' => $this->formatBytes($free),
'usage' => round($usage_percentage, 2) . '%'
]
];
}
return $results;
}
/**
* 检查是否有磁盘空间告警
*/
public function checkAlerts() {
$usage = $this->getDiskUsage();
$alerts = [];
foreach ($usage as $path => $info) {
if ($info['status'] === 'warning') {
$alerts[] = [
'path' => $path,
'label' => $info['label'],
'usage' => $info['formatted']['usage'],
'free' => $info['formatted']['free']
];
}
}
return $alerts;
}
/**
* 生成HTML格式的报告
*/
public function generateHtmlReport() {
$usage = $this->getDiskUsage();
$alerts = $this->checkAlerts();
$html = '<div class="disk-report">';
$html .= '<h3>磁盘空间使用报告</h3>';
$html .= '<table class="table">';
$html .= '<thead><tr><th>位置</th><th>总空间</th><th>已用空间</th><th>可用空间</th><th>使用率</th><th>状态</th></tr></thead>';
$html .= '<tbody>';
foreach ($usage as $info) {
$status_class = $info['status'] === 'warning' ? 'warning' : ($info['status'] === 'error' ? 'danger' : 'success');
$status_text = $info['status'] === 'warning' ? '警告' : ($info['status'] === 'error' ? '错误' : '正常');
$html .= "<tr class='table-{$status_class}'>";
$html .= "<td><strong>{$info['label']}</strong><br><small>{$info['path']}</small></td>";
$html .= "<td>{$info['formatted']['total']}</td>";
$html .= "<td>{$info['formatted']['used']}</td>";
$html .= "<td>{$info['formatted']['free']}</td>";
$html .= "<td><div class='progress' style='height: 20px;'>";
$html .= "<div class='progress-bar bg-{$status_class}' role='progressbar' style='width: {$info['usage_percentage']}%'>";
$html .= "{$info['formatted']['usage']}</div></div></td>";
$html .= "<td><span class='badge bg-{$status_class}'>{$status_text}</span></td>";
$html .= "</tr>";
}
$html .= '</tbody></table>';
if (!empty($alerts)) {
$html .= '<div class="alert alert-warning">';
$html .= '<h5><i class="fas fa-exclamation-triangle"></i> 磁盘空间警告</h5>';
foreach ($alerts as $alert) {
$html .= "<p>{$alert['label']} ({$alert['path']}) 使用率已达到 {$alert['usage']},仅剩 {$alert['free']} 可用空间</p>";
}
$html .= '</div>';
}
$html .= '</div>';
return $html;
}
/**
* 字节格式化辅助函数
*/
private function formatBytes($bytes, $precision = 2) {
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= pow(1024, $pow);
return round($bytes, $precision) . ' ' . $units[$pow];
}
}
// 使用示例
$monitor = new DiskMonitor();
echo "磁盘使用情况:\n";
print_r($monitor->getDiskUsage());
// 检查告警
$alerts = $monitor->checkAlerts();
if (!empty($alerts)) {
echo "\n警告:以下磁盘空间不足:\n";
foreach ($alerts as $alert) {
echo "- {$alert['label']}: 使用率 {$alert['usage']},剩余 {$alert['free']}\n";
}
}
// 生成HTML报告
// echo $monitor->generateHtmlReport();
?>
示例 4:跨平台兼容性处理
<?php
/**
* 跨平台磁盘空间获取函数
*/
function get_crossplatform_disk_space($path = null) {
// 如果没有指定路径,使用默认路径
if ($path === null) {
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
$path = 'C:'; // Windows默认C盘
} else {
$path = '/'; // Unix/Linux默认根目录
}
}
// Windows特定处理
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
// Windows下,确保路径以盘符加冒号开头
if (preg_match('/^[a-zA-Z]:/', $path)) {
if (!is_dir($path) && !file_exists($path . '\\')) {
// 尝试添加反斜杠
$path = rtrim($path, '\\') . '\\';
}
}
} else {
// Unix/Linux下,确保路径存在且可访问
if (!is_dir($path)) {
// 尝试使用父目录
$parent = dirname($path);
if (is_dir($parent)) {
$path = $parent;
} else {
$path = '/'; // 回退到根目录
}
}
}
// 获取磁盘空间
$free = disk_free_space($path);
$total = disk_total_space($path);
if ($free === false || $total === false) {
return [
'success' => false,
'error' => '无法获取磁盘空间信息',
'path' => $path,
'os' => PHP_OS
];
}
return [
'success' => true,
'path' => $path,
'os' => PHP_OS,
'free' => $free,
'total' => $total,
'used' => $total - $free,
'free_percentage' => ($free / $total) * 100,
'formatted' => [
'free' => format_bytes($free),
'total' => format_bytes($total),
'used' => format_bytes($total - $free)
]
];
}
// 辅助函数:格式化字节
function format_bytes($bytes, $precision = 2) {
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= pow(1024, $pow);
return round($bytes, $precision) . ' ' . $units[$pow];
}
// 使用示例
echo "操作系统: " . PHP_OS . "\n\n";
// 测试不同路径
$test_paths = ['.', '/', '/tmp'];
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
$test_paths = ['.', 'C:', 'D:'];
}
foreach ($test_paths as $path) {
$result = get_crossplatform_disk_space($path);
if ($result['success']) {
echo "路径: {$result['path']}\n";
echo "总空间: {$result['formatted']['total']}\n";
echo "可用空间: {$result['formatted']['free']}\n";
echo "已用空间: {$result['formatted']['used']}\n";
echo "可用比例: " . round($result['free_percentage'], 2) . "%\n";
echo str_repeat("-", 40) . "\n";
} else {
echo "路径 {$path}: {$result['error']}\n";
}
}
?>
示例 5:磁盘空间日志记录
<?php
/**
* 磁盘空间日志记录器
*/
class DiskSpaceLogger {
private $logFile;
private $threshold;
public function __construct($logFile = 'disk_space.log', $threshold = 10) {
$this->logFile = $logFile;
$this->threshold = $threshold; // 当可用空间百分比低于此值时记录警告
}
/**
* 记录磁盘空间信息
*/
public function logDiskSpace($path = '/') {
$free = disk_free_space($path);
$total = disk_total_space($path);
if ($free === false || $total === false) {
$this->writeLog("ERROR", $path, "无法获取磁盘空间信息");
return false;
}
$used = $total - $free;
$free_percentage = ($free / $total) * 100;
$used_percentage = 100 - $free_percentage;
$timestamp = date('Y-m-d H:i:s');
$free_formatted = $this->formatBytes($free);
$total_formatted = $this->formatBytes($total);
$message = sprintf(
"路径: %s | 总空间: %s | 可用空间: %s | 可用率: %.2f%% | 使用率: %.2f%%",
$path,
$total_formatted,
$free_formatted,
$free_percentage,
$used_percentage
);
if ($free_percentage < $this->threshold) {
$this->writeLog("WARNING", $path, $message);
} else {
$this->writeLog("INFO", $path, $message);
}
return true;
}
/**
* 批量监控多个路径
*/
public function logMultiplePaths($paths) {
$results = [];
foreach ($paths as $path) {
$results[$path] = $this->logDiskSpace($path);
}
return $results;
}
/**
* 读取日志文件
*/
public function readLog($limit = 100) {
if (!file_exists($this->logFile)) {
return [];
}
$lines = file($this->logFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$lines = array_reverse($lines); // 最新的在前
$lines = array_slice($lines, 0, $limit);
$logs = [];
foreach ($lines as $line) {
$parts = explode(' | ', $line);
if (count($parts) >= 4) {
$logs[] = [
'timestamp' => $parts[0],
'level' => $parts[1],
'path' => $parts[2],
'message' => implode(' | ', array_slice($parts, 3))
];
}
}
return $logs;
}
/**
* 清理旧日志
*/
public function cleanupLog($days = 30) {
if (!file_exists($this->logFile)) {
return false;
}
$lines = file($this->logFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$cutoff = time() - ($days * 24 * 60 * 60);
$newLines = [];
foreach ($lines as $line) {
$parts = explode(' | ', $line);
if (count($parts) >= 4) {
$logTime = strtotime($parts[0]);
if ($logTime >= $cutoff) {
$newLines[] = $line;
}
}
}
file_put_contents($this->logFile, implode(PHP_EOL, $newLines) . PHP_EOL);
return true;
}
/**
* 写入日志
*/
private function writeLog($level, $path, $message) {
$timestamp = date('Y-m-d H:i:s');
$logEntry = sprintf(
"%s | %s | %s | %s",
$timestamp,
$level,
$path,
$message
);
file_put_contents($this->logFile, $logEntry . PHP_EOL, FILE_APPEND | LOCK_EX);
}
/**
* 字节格式化
*/
private function formatBytes($bytes, $precision = 2) {
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= pow(1024, $pow);
return round($bytes, $precision) . ' ' . $units[$pow];
}
}
// 使用示例
$logger = new DiskSpaceLogger('disk_monitor.log', 10);
// 记录当前目录的磁盘空间
$logger->logDiskSpace('.');
// 记录多个路径
$paths = ['/', '/tmp', '/var', '/home'];
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
$paths = ['C:', 'D:', 'E:'];
}
$logger->logMultiplePaths($paths);
// 读取最近的日志
$recentLogs = $logger->readLog(5);
echo "最近的磁盘空间日志:\n";
foreach ($recentLogs as $log) {
echo "[{$log['timestamp']}] [{$log['level']}] {$log['message']}\n";
}
// 每月清理一次旧日志
// $logger->cleanupLog(30);
?>
系统兼容性
| 操作系统 |
支持情况 |
注意事项 |
| Windows |
完全支持 |
可以使用盘符(如"C:")或目录路径 |
| Linux |
完全支持 |
需要读取目录的权限,返回挂载点的空间信息 |
| macOS |
完全支持 |
与Linux类似,基于Unix系统 |
| FreeBSD |
完全支持 |
与Linux类似 |
| Solaris |
完全支持 |
与Unix系统类似 |
相关函数
- 错误处理:始终检查disk_free_space()的返回值是否为false
- 字节转换:将字节转换为易读的格式(如MB、GB)
- 权限检查:确保对目标目录有读取权限
- 缓存意识:结果可能被缓存,对于实时性要求高的应用需要谨慎
- 监控告警:在生产环境中设置磁盘空间监控和告警
- 日志记录:记录磁盘空间变化,便于容量规划和故障排查
- 跨平台考虑:编写跨平台代码时注意路径格式差异
- 性能优化:避免频繁调用,特别是对大容量磁盘或网络存储
1. 文件上传前的空间检查
<?php
function can_upload_file($file_size, $directory = '.') {
$free_space = disk_free_space($directory);
if ($free_space === false) {
return ['can_upload' => false, 'reason' => '无法获取磁盘空间'];
}
// 预留10%的缓冲空间
$required_space = $file_size * 1.1;
if ($free_space > $required_space) {
return ['can_upload' => true, 'free_space' => $free_space];
} else {
return [
'can_upload' => false,
'reason' => '磁盘空间不足',
'free_space' => $free_space,
'required_space' => $required_space
];
}
}
// 使用示例
$file_size = 50 * 1024 * 1024; // 50MB
$result = can_upload_file($file_size, '/uploads');
if ($result['can_upload']) {
echo "可以上传文件,可用空间: " . format_bytes($result['free_space']);
} else {
echo "无法上传: " . $result['reason'];
}
?>
2. 数据库备份前的空间检查
<?php
function check_backup_space($estimated_size, $backup_dir = '/backups') {
$free = disk_free_space($backup_dir);
if ($free === false) {
return false;
}
// 需要估计大小的2倍空间(备份+压缩)
$required = $estimated_size * 2;
return [
'can_backup' => $free > $required,
'free_space' => $free,
'required_space' => $required,
'formatted' => [
'free' => format_bytes($free),
'required' => format_bytes($required)
]
];
}
?>