PHP chmod() 函数

说明: chmod() 函数改变指定文件的权限模式。

语法

bool chmod ( string $filename , int $mode )

参数说明

参数 描述
filename 必需。要改变权限的文件路径
mode 必需。权限值,通常是一个八进制数
例如:0755、0644等

权限模式说明

八进制权限表示法

权限 数字 说明
只读 4 r--
只写 2 -w-
只执行 1 --x
读写 6 (4+2) rw-
读执行 5 (4+1) r-x
读写执行 7 (4+2+1) rwx

常见权限示例

  • 0755 - 所有者:读写执行,组和其他:读执行
  • 0644 - 所有者:读写,组和其他:只读
  • 0777 - 所有人:读写执行
  • 0750 - 所有者:读写执行,组:读执行
  • 0600 - 所有者:读写,其他:无权限

返回值

  • 成功时返回 TRUE
  • 失败时返回 FALSE

注意事项

  • 只有文件所有者或超级用户(root)可以修改文件权限
  • Windows 系统中此函数部分功能受限
  • 权限值通常以八进制表示,前面要加0(如0755)
  • 使用 clearstatcache() 清除文件状态缓存
  • 注意安全风险,避免给文件过高的权限

示例

示例 1:基本使用

<?php
// 设置文件为所有者读写,其他只读
$filename = "test.txt";

if (chmod($filename, 0644)) {
    echo "文件权限已成功修改为 0644";
} else {
    echo "文件权限修改失败";
}
?>

示例 2:设置可执行权限

<?php
// 设置脚本文件为可执行
$script = "script.sh";

if (chmod($script, 0755)) {
    echo "脚本已设置为可执行 (0755)";
} else {
    echo "权限设置失败";
}
?>

示例 3:设置私有文件权限

<?php
// 设置配置文件为只有所有者可读写
$config = "config.php";

// 0600 表示所有者读写,其他无权限
if (chmod($config, 0600)) {
    echo "配置文件已设置为私有 (0600)";

    // 验证权限
    $perms = fileperms($config);
    echo "\n当前权限: " . decoct($perms & 0777);
} else {
    echo "权限设置失败";
}
?>

示例 4:递归修改目录权限

<?php
/**
 * 递归修改目录及其内容的权限
 */
function chmod_recursive($path, $filemode, $dirmode) {
    if (!file_exists($path)) {
        return false;
    }

    if (is_dir($path)) {
        // 修改目录权限
        if (!chmod($path, $dirmode)) {
            return false;
        }

        // 遍历目录内容
        $items = scandir($path);
        foreach ($items as $item) {
            if ($item == '.' || $item == '..') {
                continue;
            }

            $itempath = $path . '/' . $item;
            chmod_recursive($itempath, $filemode, $dirmode);
        }
    } else {
        // 修改文件权限
        return chmod($path, $filemode);
    }

    return true;
}

// 使用示例
$directory = '/var/www/html/temp';
$result = chmod_recursive($directory, 0644, 0755);
if ($result) {
    echo "目录权限递归修改成功";
} else {
    echo "权限修改失败";
}
?>

示例 5:获取和显示当前权限

<?php
function get_permissions_string($filename) {
    if (!file_exists($filename)) {
        return "文件不存在";
    }

    $perms = fileperms($filename);

    // 判断类型
    $type = '';
    if (($perms & 0xC000) == 0xC000) $type = 's'; // Socket
    elseif (($perms & 0xA000) == 0xA000) $type = 'l'; // 符号链接
    elseif (($perms & 0x8000) == 0x8000) $type = '-'; // 普通文件
    elseif (($perms & 0x6000) == 0x6000) $type = 'b'; // 块设备
    elseif (($perms & 0x4000) == 0x4000) $type = 'd'; // 目录
    elseif (($perms & 0x2000) == 0x2000) $type = 'c'; // 字符设备
    elseif (($perms & 0x1000) == 0x1000) $type = 'p'; // 管道
    else $type = 'u'; // 未知

    // 所有者权限
    $owner = (($perms & 0x0100) ? 'r' : '-');
    $owner .= (($perms & 0x0080) ? 'w' : '-');
    $owner .= (($perms & 0x0040) ? (($perms & 0x0800) ? 's' : 'x') : (($perms & 0x0800) ? 'S' : '-'));

    // 组权限
    $group = (($perms & 0x0020) ? 'r' : '-');
    $group .= (($perms & 0x0010) ? 'w' : '-');
    $group .= (($perms & 0x0008) ? (($perms & 0x0400) ? 's' : 'x') : (($perms & 0x0400) ? 'S' : '-'));

    // 其他用户权限
    $other = (($perms & 0x0004) ? 'r' : '-');
    $other .= (($perms & 0x0002) ? 'w' : '-');
    $other .= (($perms & 0x0001) ? (($perms & 0x0200) ? 't' : 'x') : (($perms & 0x0200) ? 'T' : '-'));

    return $type . $owner . $group . $other . ' (' . decoct($perms & 0777) . ')';
}

// 使用示例
$file = 'example.php';
echo "文件: $file\n";
echo "权限: " . get_permissions_string($file);
?>

错误处理示例

<?php
function safe_chmod($filename, $mode) {
    if (!file_exists($filename)) {
        return ['success' => false, 'message' => '文件不存在'];
    }

    // 检查当前用户权限
    $current_uid = posix_getuid();
    $file_owner = fileowner($filename);

    if ($current_uid != 0 && $current_uid != $file_owner) {
        return ['success' => false, 'message' => '权限不足:只有文件所有者或root用户可以修改权限'];
    }

    // 验证权限模式
    if (!is_int($mode) || $mode < 0 || $mode > 07777) {
        return ['success' => false, 'message' => '无效的权限模式'];
    }

    // 尝试修改权限
    if (chmod($filename, $mode)) {
        clearstatcache();
        return ['success' => true, 'message' => '权限修改成功'];
    } else {
        $error = error_get_last();
        return ['success' => false, 'message' => '权限修改失败: ' . $error['message']];
    }
}

// 使用示例
$result = safe_chmod('important.txt', 0600);
if ($result['success']) {
    echo $result['message'];
} else {
    echo "错误: " . $result['message'];
}
?>

相关函数

最佳实践
  1. 遵循最小权限原则:只给予必要的权限
  2. 配置文件保护:敏感配置文件应设置为 0600 或 0640
  3. 可执行文件:脚本文件通常设置为 0755
  4. 上传目录:设置为 0755,文件设置为 0644
  5. 清除缓存:修改权限后使用 clearstatcache()
  6. 错误处理:始终检查 chmod() 的返回值
  7. 权限验证:修改前后使用 fileperms() 验证