Tag: «php»
Заметка про сессии в PHP и Garbage Collector
Неприятную штуку тут на одном из рабочих серваков обнаружил.
Исторически сложилось, что при старте PHP-движка сайта выставляется значение:
session_save_path( PATH_TMP );
ini_set( 'session.gc_maxlifetime', 1800 );
То бишь у нас кастомная директория для хранения сессий, и время жизни ей выставлено в полчаса для garbage collector.
На сервере используется php-fpm. Обнаружил проблемы в логах - будто бы место закончилось на диске. Хотя его ещё дофига. Сразу мысль - где-то дофига файлов мелких насоздавалось. Как оказалось - не стирались файлы сессий в нашей кастомной директории. Стал копаться - на php.net нахожу параметр session.gc_probability, который в php.ini должен быть выставлен в 1 - это вероятность того, что при выполнении скрипта запустится ещё и garbage collector.
В подсказках пользователя запись, что Debian выставляет этот параметр в 0. Гугление говорит, что это связано с выставленными на дефолтную папку /var/lib/php5 правами, которые не позволяют php-шному garbage collection очищать старые файлы оттуда. То есть он отрубает garbage collector у php и вроде как от рута запускает какое-то своё cron-задание для очистки. Ищет он файлы, похоже, в стандартной директории, а т.к. оно не совпадает с нашей директорией PATH_TMP - то сессии не удалялись.
Вот такие пироги. Выход - либо настроить своё cron-задание для очистки, например:
0,30 * * * * find /path/to/tmp -mmin +30 -exec rm {} \;
Либо в php.ini прописывать дефолтную папку. Но, например, если на сайте 2 проекта, которые используют разные временные папки для хранения сессий, то тут уже придётся для обоих как-то что-то настраивать.
Либо при старте скрипта добавить строчку: ini_set('session.gc_probability', 1);
Лично мне больше нравится своё cron-задание. Хотя может и добавление ещё одной строчки в скрипт - лучше, т.к. на будущее может избавить от этой проблемы. Хотя cron как-то кажется надёжнее. Осталось придумать теперь, как мне удалить накопившиеся за 6 месяцев файлы. Midnight Commander часа 2 у меня сканировал папку. Когда счётчик перевалил за 49 миллионов - я забил на сканирование, поставил удаление и пошёл спать.
Такие дела.
comment commentsОпределение ориентации фото на PHP через EXIF
Шпаргалка.
Вертикальные фотографии, снятые в портретном режиме на Android и iPhone сохраняются как горизонтальные, но в EXIF пишется ориентация фото.
Если вывести значение команды:
$exif = exif_read_data( $existingFilePath, 0, true);
То увидим среди значений массива:
array
(
...
[IFD0] => Array
(
[Make] => Sony
[Model] => LT25i
[Orientation] => 6
[XResolution] => 72/1
[YResolution] => 72/1
[ResolutionUnit] => 2
[Software] => 9.1.A.1.145_58_f100
[DateTime] => 2013:07:26 17:00:01
[YCbCrPositioning] => 1
[Exif_IFD_Pointer] => 214
[GPS_IFD_Pointer] => 626
)
...
)
В данном случае это значит, что при показе этой фотографии - отображающее его приложение должно повернуть на 90 градусов фото, т.к. фото в портретной ориентации.
Чтобы при заливке картинок на сервер и изменении их (создание уменьшенной копии, создание превьюшки) не было косяков, можно определять такие фотки кодом:
<?php
imagecopyresampled( $resultImage, $sourceImage, 0, 0, 0, 0, $new_width, $new_height, $width, $height );
$exif = exif_read_data( $existingFilePath, 0, true);
if( false === empty( $exif['IFD0']['Orientation'] ) ) {
switch( $exif['IFD0']['Orientation'] ) {
case 8:
$resultImage = imagerotate( $resultImage, 90, 0 );
break;
case 3:
$resultImage = imagerotate( $resultImage,180,0);
break;
case 6:
$resultImage = imagerotate( $resultImage,-90,0);
break;
}
}
Что интересно - Windows Phone сохраняет фотографию в портретной ориентации как вертикальное изображение.
comment commentsFCKEditor и ошибка Access Denied
Обновил на своём серваке до последних стабильных версий Nginx и PHP до последних стабильных версий. PHP на данный момент 5.4.6.
После обновления перестал работать FCKEditor, вместо него выдавалась надпись «Access Denied».
FCKEditor на странице выводится через iframe, в котором, собственно и висит эта надпись. Поглядел исходники редактора, думал, что может где-то проверка версии php где-то, но ничего особого не нашёл. В ifame грузится файлик fckeditor/editor/fckeditor.html. Открыл его отдельно - та же ошибка. Подумал уже на Nginx, но, как оказалось, это вовсе не Nginx, и не исходники, а как раз PHP (php-fpm).
Гуглить по словам «Access Denied» было нелегко, но, заглянув в логи ошибок, увидел ключевое слово security.limit_extensions. Судя по названию, этот параметр в конфиге php-fpm.conf отвечает за то, в файлах с каким расширением исполнять php-код. Начиная с версии PHP 5.3.9, в целях безопасности, если этот параметр не указан в конфиге, то код исполняется только в файлах .php (как было до этого не знаю), а сам FCKEditor как-то хитро/криво через php подключается, что получается исполнение кода в том самом файле fckeditor.html (хотя внутри его нет). Там просто длинная схема фреймворка. Собственно поэтому php-fpm и возвращал «Access Denied».
Решение: в php-fpm.conf, а лучше в .conf-файле пула (вроде /etc/php-fpm/pulls/mysite.conf) добавить строчку:
security.limit_extensions = .php .html
Такое вот решение. Убил почти полтора часа на его поиск, т.к. не зная чужого кода не сразу понял, куда же копать. Поэтому оставлю это здесь. А может кому ещё пригодится.
comment commentsОбрезание слэша в url с 301 редиректом
А собственно почему бы и не повесить этот тут, потом будет легко найти, когда опять понадобится. Зачастую поисковики воспринимают страницы вида:
//arm1.ru/blog/yandex-upal-panika-v-twitter
//arm1.ru/blog/yandex-upal-panika-v-twitter/
как разные страницы. Получается, что один и тот же контент технически по двум разным страницам, что не есть хорошо. Под катом код для автоматического отрезания символа / в конце с 301 редиректом, чтобы поисковики не дублировали страницы при индексировании.
# убираем QUERY_STRING строку из REQUEST_URI
$uri = $_SERVER['REQUEST_URI'];
if ( false === empty( $_SERVER['QUERY_STRING'] ) )
$uri = str_replace( '?' . $_SERVER['QUERY_STRING'], '', $uri );
# переадресация через 301 редирект при присутствии слэша в конце $uri
if ( substr( $uri, -1 ) == '/' && strlen( $uri ) > 1 ) {
$queryString = '';
if ( false === empty( $_SERVER['QUERY_STRING'] ) )
$queryString = '?' . $_SERVER['QUERY_STRING'];
header( 'Location: ' . substr( $uri, 0, -1 ) . $queryString, true, 301 );
exit;
}
comment comments
Отправка сообщений в Twitter через php
Давно хотел выложить свой простенький набор функций для отправки твитов в Twitter. Может кому полезно будет, т.к. мне не сразу всё далось, особенно фомирование подписи. Плюс это моя попытка закрепить в голове то, что было познано и закодено. По-моему нет лучше способа это сделать, чем попытаться кому-то это объяснить :) Под катом описание и код.
comment commentsРесайз анимированных gif-изображений с помощью Imagick
По работе столкнулся с необходимостью обработки анимированных gif-аватарок. Исходные картинки могут быть любого размера, и их нужно уменьшить до нужного размера с кадрированием до квадрата. Под катом - как мы это решали.
comment commentsПростой онлайн TimeStamp конвертер
По работе периодически приходится смотреть какие-то данные из базы. Время мы в основном храним в TimeStamp (кто не знает - это количество секунд, прошедших с сотворения мира Unix, то есть 1 января 1970 года).
По цифре вроде 1305233826 хрен поймёшь, что это за дата. Каждый раз писать в каком-нибудь скрипте конвертирование неудобно, поэтому сделал онлайн-конвертер. Показывает время в удобочитаемом виде.
Enjoy. Online TimeStamp Converter