17
2011
Удаление устаревших 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, ничего сказать не могу, но скорее всего все это дело там реализовано аналогичным образом.
Пн | Вт | Ср | Чт | Пт | Сб | Вс |
---|---|---|---|---|---|---|
« Сен | ||||||
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 |
Метки
Рубрики
- Apache (1)
- Highload (4)
- JavaScript (1)
- Linux (3)
- MongoDB (1)
- MySQL (1)
- Perl (1)
- PHP (5)
- Python (5)
- Web-разработка (5)
- Алгоритмы (1)
- За жизнь (2)
- Конференции (6)
В 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
в остальном те же грабли. Никак не мог понять почему не чистятся файлы сессий, пока не наткнулся на данную статью. А такс крона видел нираз и каждый раз думал нафик оно тут надо? Но не дошли руки взглянуть что он вообще делает ))
Проще своим скриптом чистить
в крон