PHP не сохраняет сессии на Beget/CloudLinux — Warning: SessionHandler::write()
Warning: SessionHandler::write(): open(/tmp/php_sess/sites/…/sess_…) failed: No such file or directory. Решение — переопределить путь сессий через PHP-код: ini_set('session.save_path', …).
Почему это происходит
CloudLinux PHP Selector принудительно задаёт путь для хранения PHP-сессий через директиву php_admin_value в конфигурации Apache. Путь выглядит так:
/tmp/php_sess/sites/2753/
где 2753 — внутренний ID аккаунта на сервере.
Проблема в том, что:
- Директория
/tmp/php_sess/sites/2753/может не существовать — её должен создать CloudLinux при активации PHP Selector, но это не всегда срабатывает /tmpочищается при перезагрузке сервера — после ребута директория пропадаетphp_admin_valueимеет высший приоритет — его нельзя переопределить через.user.iniили.htaccess
php_admin_value session.save_path в Apache-конфиге имеет приоритет выше, чем .user.ini. Поэтому создать файл .user.ini с session.save_path = … — бесполезно.
Как исправить
Единственный надёжный способ — переопределить путь сессий прямо в коде PHP, до вызова session_start().
Шаг 1: Создать директорию для сессий
В корне проекта создайте папку, куда у PHP будет доступ на запись. Например, в системном storage:
mkdir -p ~/public_html/system/storage/sessions
chmod 733 ~/public_html/system/storage/sessions
Права 733 (drwx-wx-wx) дают PHP-процессу (который выполняется от владельца файла) право создавать и читать файлы сессий.
Шаг 2: Добавить ini_set() в код
Найдите место, где в вашей CMS стартует сессия. Добавьте строку ini_set('session.save_path', …) перед session_start().
Для OpenCart 2.x файл: system/library/session.php, метод __construct():
// Было:
if ($this->adaptor && !session_id()) {
ini_set('session.use_only_cookies', 'Off');
ini_set('session.use_cookies', 'On');
ini_set('session.use_trans_sid', 'Off');
ini_set('session.cookie_httponly', 'On');
…
session_start();
}
// Стало:
if ($this->adaptor && !session_id()) {
ini_set('session.save_path', DIR_SYSTEM . 'storage/sessions');
ini_set('session.use_only_cookies', 'Off');
ini_set('session.use_cookies', 'On');
ini_set('session.use_trans_sid', 'Off');
ini_set('session.cookie_httponly', 'On');
…
session_start();
}
wp-config.php перед строкой require_once(ABSPATH . 'wp-settings.php');:
ini_set('session.save_path', dirname(ABSPATH) . '/sessions');
Не забудьте создать папку sessions уровнем выше wp-content и дать права 733.
Шаг 3: Запретить доступ к папке сессий из веба
Добавьте .htaccess внутрь папки сессий:
# sessions/.htaccess
Require all denied
Или (для Apache 2.2):
Order Deny,Allow
Deny from all
Проверка результата
Чтобы убедиться, что сессии пишутся в новую директорию:
Зайдите на сайт (фронтенд), чтобы PHP создал сессию.
Проверьте, что в папке появились файлы
sess_*:
ls -la ~/public_html/system/storage/sessions/
# Результат:
# -rw------- 1 user user … sess_abc123def456…
Проверьте, что ошибка пропала из логов:
tail -f ~/public_html/system/storage/logs/error.log
# Сессионных варнингов быть не должно
Попробуйте войти в админку — если раньше не пускало (редирект с меняющимся ID сессии), теперь вход должен работать.
Когда способ не сработает
Если после ini_set() ошибка осталась — проверьте:
- Права на папку: у PHP-процесса должно быть право записи. Права 733 или 777 (временная проверка).
- PHP-FPM: если сайт работает через PHP-FPM (а не mod_php), убедитесь, что путь существует для пользователя, от которого запущен пул FPM.
- Пользователь: на Beget сайты обычно работают от владельца аккаунта. Если
ls -laпоказывает другого владельца — исправьтеchown. - CloudLinux CageFS: может изолировать пути. Если папка сессий внутри
public_html— всё в порядке, CageFS не блокирует запись туда.
Частые вопросы
Не получается настроить сессии?
Сталкиваюсь с CloudLinux-багами на Beget, Timeweb, SpaceWeb. Знаю все обходы. Напишите — помогу за полчаса.