Апр
17
2011

Удаление устаревших PHP сессий в Debian

Удаление устаревших PHP сессий в Debian Ни для кого не секрет, что в PHP существует так называемый «garbage collector» — сборщик мусора для удаления устаревших сессионных данных. По умолчанию, garbage collector подчищает только те сессии, которые не были использваны в течении предыдущих 24х минут (время задается в директиве session.gc_maxlifetime файла конфигурации php.ini), а сами сессии храняться в файлах. Так же garbage collector запускается при старте механизма сессий (т. е.session_start()), но не каждый раз, а с некой периодичностью, определяемой соотношением величин session.gc_probability / session.gc_divisor — это «вероятность» запуска сборщика мусора. И вообщем-то казалось бы все довольно очевидно и кроссплатформено, но … оказывается что в Debian-е все устроено не совсем так, как у всех :)

Cтолкнулся я с этим совсем недавно. На одном из проектов на сервере под Debian-ом возникла небольшая проблемка — сессии наотрез отказывались удаляться. Оказывается причиной всему была нестандартная реализация механизма GC в PHP под Debian-ом. Исходя из соображений безопасности стандартный GC был вообще полностью отключен, а вместо него отрабатывал вот такой вот CRON-овский таск: /etc/cron.d/php5 (собственно, проблема заключалась в том, что этот таск был по каким-то неведомым для меня причинам закомменчен)

# /etc/cron.d/php5: crontab fragment for php5
#  This purges session files older than X, where X is defined in seconds
#  as the largest value of session.gc_maxlifetime from all your php.ini
#  files, or 24 minutes if not defined.  See /usr/lib/php5/maxlifetime
 
# Look for and purge old sessions every 30 minutes
09,39 *     * * *     root   [ -x /usr/lib/php5/maxlifetime ] && [ -d /var/lib/php5 ] && find /var/lib/php5/ -type f -cmin +$(/usr/lib/php5/maxlifetime) -print0 | xargs -n 200 -r -0 rm

Как видно из листинга выше, таск выполняется каждые 9 и 39 минут, при помощи вспомогательного bash скрипта /usr/lib/php5/maxlifetime парсит php.ini на наличие директивы session.gc_maxlifetime, и затем просто тупо удаляет все найденные «устаревшие» файлы из директории /var/lib/php5. Скрипт /usr/lib/php5/maxlifetime:

#!/bin/sh -e
 
max=1440
 
for ini in /etc/php5/*/php.ini; do
        cur=$(sed -n -e 's/^[[:space:]]*session.gc_maxlifetime[[:space:]]*=[[:space:]]*\([0-9]\+\).*$/\1/p' $ini 2>/dev/null || true);
        [ -z "$cur" ] && cur=0
        [ "$cur" -gt "$max" ] && max=$cur
done
 
echo $(($max/60))
 
exit 0

Один из минусов данной реализации: жестко заданная директория /var/lib/php5. Конечно же, эту директорию несложно поменять, но для этого надо лезть в кроновский таск, что довольно неочевидно. Жестко заданны 9 и 39 минут (хотя в 90% случаев заданного интервала вполне будет хватать). А ещё к минусам можно отнести поиск директивы session.gc_maxlifetime исключительно в /etc/php5/*/php.ini, хотя поидее она может быть задана в файлах /etc/php5/*/conf.d/*.ini . Кстати говоря, оказывается эта бага описана на багтрекере Debian: #508007. Само собой разумеется, это упущение тоже не так уж сложно поправить, но тем не менее для этого необходимо немного пошевелить мозгами, попереписывать bash-скрипты… :) У данного подхода имеются и свои плюсы: один из них — безопасность (ага, ради чего все и затевалось), а второй — скрипт удаления сессий не связан с интерпритаром, что делает его менее «нагруженным».

Отмечу ещё раз — данный механизм относится ТОЛЬКО к реализации стандартного GC, основанного на хранении данных сессии в файлах. При переопределении механизма сохранения сессий в БД или в memcache, переопределенный GC (например, через функцию session_set_save_handler()) будет отрабатывать так, как и положено согласно документации PHP.

P.S. Аналогичный механизм работы GC присутствует и в дистрибутиве Ubuntu. Оно и ясно — производная от Debian-а. Про остальные дистрибутивы (типо Dreamlinux), основанные на Debian, ничего сказать не могу, но скорее всего все это дело там реализовано аналогичным образом.

Комментарии (3)

  • В ubuntu такс крона выглядит так,

    [ -x /usr/lib/php5/maxlifetime ] && [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) -delete

    в остальном те же грабли. Никак не мог понять почему не чистятся файлы сессий, пока не наткнулся на данную статью. А такс крона видел нираз и каждый раз думал нафик оно тут надо? Но не дошли руки взглянуть что он вообще делает ))

  • Проще своим скриптом чистить

  • 0 1 * * * find /var/lib/php5 -name "sess_*" -type f -mtime -30 -delete

    в крон

Оставить комментарий

CAPTCHA image


Поля, отмеченные * обязательны для заполнения


XHTML: Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">