Управление правами файлов в PHP: практическое руководство

Раздел: Администрирование PHP -> Управление правами доступа

Изменение прав доступа к файлам в PHP

Как эффективно изменить права на файл или директорию в PHP?

Наиболее распространённый и универсальный способ - использование функции chmod(). Она позволяет задать права в виде восьмеричного числа: 0644 (файл) или 0755 (директория).

$file = '/var/www/html/index.php';
$permissions = 0644; // владелец: rw-, группа: r--, остальные: r--
if (chmod($file, $permissions)) {
    echo "Права успешно установлены.";
} else {
    echo "Ошибка при установке прав.";
}

Php права на файл (установка прав на файл в php)

Важно: права задаются в восьмеричной системе (ведущий ноль). Функция возвращает true при успехе и false при неудаче. Проверять результат обязательно.

Типичные проблемы:

  • PHP-скрипт выполняется от пользователя www-data (или другого веб-пользователя), и он может не иметь прав на смену прав, если файл принадлежит другому пользователю.
  • Установка прав на уровне ядра может быть заблокирована настройками ОС (например, в контейнере или на некоторых хостингах).
  • Ошибка при передаче десятичного числа вместо восьмеричного: chmod($file, 755) установит неверные права (число 755 десятичное = 1367 в восьмеричной системе).

Решение: убедиться, что PHP-пользователь - владелец файла или имеет права суперпользователя (для chmod обычно достаточно владения). Всегда указывать восьмеричное значение с ведущим нулём.

Как установить права рекурсивно на все вложенные файлы и папки?

Используется комбинация RecursiveDirectoryIterator и chmod.

function chmodRecursive($path, $filePerm = 0644, $dirPerm = 0755) {
    $iterator = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS)
    );
    foreach ($iterator as $item) {
        if ($item->isDir()) {
            chmod($item->getPathname(), $dirPerm);
        } else {
            chmod($item->getPathname(), $filePerm);
        }
    }
}

Ошибка: рекурсивный обход может затронуть огромное количество файлов, что вызовет тайм-аут. Решение: ограничивать количество итераций или выполнять в фоновом процессе.

Как изменить владельца файла (chown) и группу (chgrp)?

Функции chown() и chgrp() изменяют владельца и группу. Требуют права суперпользователя.

$file = '/tmp/test.txt';
if (chown($file, 'www-data')) {
    echo "Владелец изменён.";
}
if (chgrp($file, 'www-data')) {
    echo "Группа изменена.";
}

Ошибка: Operation not permitted - PHP скрипт не запущен от root. Решение: использовать sudo через exec или изменить политики (не рекомендуется совместное размещение с веб-сервером).

Как управлять правами при загрузке файлов (upload)?

Установить правильную маску прав по умолчанию с помощью umask().

$oldmask = umask(0022); // сброс маски: новые файлы получат 0644, папки 0755
move_uploaded_file($_FILES['file']['tmp_name'], $destination);
umask($oldmask); // восстановление маски

Проблема: неверная маска может привести к слишком открытым правам (например, 0777). Решение: явно задавать права после перемещения через chmod().

Как работать с правами через FTP, SSH2 или потоковые обёртки?

Если файлы находятся на удалённом сервере или PHP не имеет прямого доступа к файловой системе, можно использовать FTP-функции или SSH2.

// FTP
$conn = ftp_connect('example.com');
ftp_login($conn, 'user', 'password');
ftp_chmod($conn, 0644, '/remote/file.txt');
ftp_close($conn);

// SSH2
$connection = ssh2_connect('example.com', 22);
ssh2_auth_password($connection, 'user', 'pass');
$sftp = ssh2_sftp($connection);
ssh2_sftp_chmod($sftp, '/remote/file.txt', 0644);

Ошибка: модули ftp или ssh2 могут быть не установлены. Решение: проверить extension_loaded() и установить расширения.

Как проверить текущие права файла перед изменением?

Используется fileperms() и преобразование в восьмеричный формат.

$perms = fileperms('/path/to/file');
if ($perms !== false) {
    $octal = substr(sprintf('%o', $perms), -4);
    echo "Текущие права: $octal";
}

Расширенные примеры работы с правами в PHP

Пример
// Пример 1: Установка прав 0755 для папки и рекурсивно для всех файлов
function chmodRecursiveEx($dir, $dirPerm = 0755, $filePerm = 0644) {
    $it = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS),
        RecursiveIteratorIterator::SELF_FIRST
    );
    foreach ($it as $item) {
        $path = $item->getPathname();
        if ($item->isDir()) {
            chmod($path, $dirPerm);
        } else {
            chmod($path, $filePerm);
        }
    }
}
chmodRecursiveEx('/var/www/uploads');
echo "Рекурсивное изменение завершено.";
Рекурсивное изменение завершено.
Пример
// Пример 2: Использование umask для безопасной загрузки
$uploadDir = '/var/www/uploads/';
$old = umask(0077); // новые файлы будут с правами 0700
move_uploaded_file($_FILES['avatar']['tmp_name'], $uploadDir . 'avatar.jpg');
umask($old);
echo "Файл загружен с ограниченными правами.";
Файл загружен с ограниченными правами.
Пример
// Пример 3: Изменение владельца и группы с проверкой
$file = '/etc/cron.d/mytask';
if (is_writable($file)) {
    if (chown($file, 'root') && chgrp($file, 'root')) {
        echo "Владелец и группа изменены на root.";
    } else {
        echo "Не удалось изменить владельца/группу.";
    }
} else {
    echo "Нет прав на запись.";
}
Нет прав на запись. (если скрипт не от root)
Пример
// Пример 4: Работа с правами через SSH2 (с использованием SFTP)
$connection = ssh2_connect('192.168.1.100', 22);
if (ssh2_auth_password($connection, 'admin', 'secret')) {
    $sftp = ssh2_sftp($connection);
    $remoteFile = '/data/config.ini';
    // Устанавливаем права 0600 (только владелец чтение/запись)
    if (ssh2_sftp_chmod($sftp, $remoteFile, 0600)) {
        echo "Права успешно изменены на удалённом сервере.";
    } else {
        echo "Ошибка SSH2 chmod.";
    }
} else {
    echo "Ошибка аутентификации SSH.";
}
Права успешно изменены на удалённом сервере.
Пример
// Пример 5: Получение текущих прав и вывод в человекочитаемом виде
$perms = fileperms('/usr/local/bin/script.sh');
if ($perms !== false) {
    $octal = substr(sprintf('%o', $perms), -4);
    echo "Восьмеричные права: $octal\n";
    // Двоичное представление
    echo "Двоичное представление: ";
    for ($i = 0; $i < 3; $i++) {
        echo str_pad(decbin(($perms >> 6 - $i*3) & 07), 3, '0', STR_PAD_LEFT) . ' ';
    }
}
Восьмеричные права: 0755
Двоичное представление: 111 101 101

Установка прав на файл в PHP - comments

En
Php права на файл (php)