Показаны сообщения с ярлыком ffmpeg. Показать все сообщения
Показаны сообщения с ярлыком ffmpeg. Показать все сообщения

суббота, 3 декабря 2011 г.

Chroot php-fpm в rhel6.


Возникла необходимость поставить php-fpm в chroot для увеличения безопасности одного популярного движка сайта. Небольшой рассказ о проделанной работе и возникших проблемах. Итак, php-fpm обладает замечательной возможностью запускать скрипты в chroot-окружении. Немного wikipedia: chroot — операция изменения корневого каталога в Unix-подобных операционных системах. Программа, запущенная с изменённым корневым каталогом, будет иметь доступ только к файлам, содержащимся в данном каталоге. Поэтому, если нужно обеспечить программе доступ к другим каталогам или файловым системам (например, /proc), нужно заранее смонтировать в целевом каталоге необходимые каталоги или устройства.
Немного об используемом ПО. Все крутится под 64-битной RHEL6. Настроена связка php-fpm + nginx, о настройке которой, наверно, будет рассказано в другой заметке. Сайт лежит в /data/www/DOMAIN.COM. Используются популярные библиотеки/программы для работы с видео/графикой, т.е. ffmpeg и ImageMagick.

Установка php-fpm.
a) Установить репозиторий remi:
wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
rpm -Uvh remi-release-6.rpm
b) Импорт GPG-ключа
rpmimport http://rpms.famillecollet.com/RPM-GPG-KEY-remi
c) yum -y install php-fpm

Настройка php-fpm.
Отмечу только те моменты, которые стоит изменить.

cat /etc/php-fpm.d/www.conf
; Название пула процессов
[www]
****
; Задаем пользователя, под которым будет работать php-fpm.
user = pf
; Тоже самое для группы.
group = pf
; При старте делать chroot в заданную директорию.
chroot = /data
chdir = /www/DOMAIN.COM
; Путь и параметры для отправки почты с помощью функции php mail()
php_admin_value[sendmail_path] = /usr/bin/mini_sendmail -t -fUSER@DOMAIN.COM -s192.168.0.x

****

Настройка nginx.

Параметры, которые будут передаваться FastCGI-серверу, т.е. Php-fpm. Обратите внимание, на закомментированные и рабочие строки. Nginx должен передать php-fpm параметры относительно корня chroot, т.е. НЕ /data/www/DOMAIN.COM, а /www/DOMAIN.COM.

cat /etc/nginx/fastcgi_params

fastcgi_param DOCUMENT_ROOT /www/DOMAIN.COM;
#fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SCRIPT_FILENAME /www/DOMAIN.COM$fastcgi_script_name;
#fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

Создание окружения для запуска скриптов (папки, файлы, библиотеки...)

Одна из самых интересных частей. Суть ее заключается в следующем: создаем необходимые папки в chroot-окружении, копируем необходимые библиотеки/файлы для работы сайта. Объем библиотек достаточно большой, надо внимательно скопировать нужные, в сети много скриптов, которые могут сделают за вас эту работу, но в первый раз рекомендую сделать вручную, чтобы понять что к чему.

# cd /data/
# mkdir -p /data/{bin,etc,var,lib64,tmp,usr}
# mkdir -p /data/usr/{share,bin,lib64}
# chmod 1777 tmp
для запуска ffmpeg и convert php требуется shell, придется копировать внутрь chroot bash или dash на ваш выбор.
# cp /bin/bash bin
# ln -s bash bin/sh
# cp /etc/{hosts,localtime,nsswitch.conf,resolv.conf} etc
# cp -R /usr/share/zoneinfo usr/share
# cp /usr/bin/{ffmpeg,convert} usr/bin
# cp /lib64/libnss_dns* lib64
# cp /lib64/libnss_files* lib64

Теперь важный момент — часто php-скриптам требуется определять днс-имена и временные зоны. Нужно скопировать в chroot-окружение библиотеки libnss. Для проверки определения имен я использую print_r(dns_get_record('google.com'));
Для каждого выполняемого файла в chroot-окружении необходимо скопировать нужные библиотеки (если только файл не скомпилирован статически, что бывает достаточно редко).
# ldd /usr/bin/ffmpeg
# ldd /usr/bin/convert
# ldd /bin/bash
На экран будет выведен список необходимых библиотек для указанных программ. Данные библиотеки вместе с символическими ссылками копируете в chroot-окружение (то, что лежит в /lib64 -> /data/lib64; то, что лежит в /usr/lib64 -> /data/usr/lib64).

Запуск и разбор возникающих ошибок

1. Функция php mail().
Для использования в php-скриптах функции mail() нужно либо копировать sendmail со всеми необходимыми библиотеками, либо статически слинковать mini_sendmail. Поскольку готового пакета mini_sendmail для rhel6 в репозиториях нет, придется качать и компилировать вручную.


# make
Если нижеследующей ошибки не возникает — можно пропустить.
gcc -O -s -static mini_sendmail.o -o mini_sendmail
/usr/bin/ld: cannot find -lc

Решение:
Нужно установить пакет glibc-static, который содержит все необходимые библиотеки для статической линковки программ.
# yum install glibc-static

Необязательный пункт, но все же.
Отредактируйте файл mini_sendmail.c, найдите строку:
username = getlogin();
заменить на:
username = "mini_sendmail";//getlogin();
Причем, на что вы измените имя юзера (username) роли не играет, просто это позволит избежать вызова функции getlogin() для определения вызывающего пользователя.
Для запуска необходим bash (sh) - нужно скопировать в chroot-директорию, а также скопировать нужные ему библиотеки.

2. Ошибка «php timezone database is corrupt»
Проверьте скопировали ли вы файлы /usr/share/zoneinfo в chroot.

3. Не пишутся логи ошибок php-fpm
проверьте есть ли директория /var/log/php-fpm/ внутри chroot и есть ли права у пользователя, под которым запускается php-fpm, на запись/создание файлов в данной папке.

4. Пляски вокруг ImageMagick
Появляются ошибки вида:

convert: UnableToOpenConfigureFile `delegates.xml' @ warning/configure.c/GetConfigureOptions/589.

Пришлось много гуглить, кто предлагает переустановить ImageMagick, кто скачать и перекомпилировать исходники, кто пользоваться библиотекой gd, вообщем рецептов много — выбирай на вкус. Оказалось все гораздо проще — надо скопировать необходимые конфигурационные файлы (*.xml) из папки /usr/lib64/ImageMagick-$version/ в /data/usr/lib64/ImageMagick-$version/

5. Сессии.

Почти внезапно перестали работать сессии. Связано с тем, что необходимого каталога нет в chroot-окружении. Выходов есть несколько: либо вести сессии в базе данных, либо создать необходимые папки с правами в chroot-окружении, либо изменить значение пути где хранятся сессии на /tmp.

Литература:

четверг, 10 марта 2011 г.

Установка расширения ffmpeg-php на rhel 5.5.

Установка репозитариев:
cat /etc/yum.repos.d/local.repo
[Local]
name=local
baseurl=file:///mnt/Server
enabled=1
gpgcheck=0

cat /etc/yum.repos.d/dag.repo
[Dag]
name=dag
baseurl=http://apt.sw.be/redhat/el5/en/i386/dag
enabled=1
gpgcheck=0

Скачиваем дополнительные репозитории epel и remi:
wget -c http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm
wget -c http://rpms.famillecollet.com/enterprise/remi-release-5.rpm
rpm -Uvh remi-release-5*.rpm epel-release-5*.rpm

Установка необходимых пакетов:
yum -y --enablerepo=remi,epel install mysql-server php php-devel
yum -y --enablerepo=remi,epel install php-xml (модуль dom.so)
yum -y --enablerepo=remi,epel install php-mbstring php-mcrypt php-intl php-gd
yum -y install gcc httpd re2c
yum -y install ffmpeg ffmpeg-devel libvorbis-devel

Скачиваем сам пакет ffmpeg-php:
wget -c http://switch.dl.sourceforge.net/project/ffmpeg-php/ffmpeg-php/0.6.0/ffmpeg-php-0.6.0.tbz2

tar xjf ffmpeg-php-0.6.0.tbz2

cd ffmpeg-php-0.6.0
phpize
./configure --enable-static --disable-debug
make
вылазит ошибка «error: PIX_FMT_RGBA32 undeclared»
в файле ffmpeg_frame.c меняем PIX_FMT_RGBA32 на PIX_FMT_RGB32

cp modules/ffmpeg.so /usr/lib/php/modules

echo "extension=ffmpeg.so" > /etc/php.d/ffmpeg.ini

Если в логах вылазит предупреждение «Persistent movies have been disabled in php.ini», то:
cat << EOF >> /etc/php.ini

[ffmpeg]
ffmpeg.allow_persistent=on
EOF

Также выставить date = Europe/Kiev или какой у вас часовой пояс.

service httpd restart
chkconfig httpd on

Проверка какие модули установлены и их параметры:
cat << EOF >> /var/www/html/index.php
<?php
phpinfo();
?>
EOF

Тестирование ffmpeg (естественно файл предварительно скопировать на сервер):

mkdir -p /var/www/html/tt
chown apache:apache /var/www/html/tt
cp test.avi /var/www/html/tt

cat /var/www/html/tt/test.php

<?php
$extension = "ffmpeg";
$extension_soname = $extension . "." . PHP_SHLIB_SUFFIX;
$extension_fullname = PHP_EXTENSION_DIR . "/" . $extension_soname;

if(!extension_loaded($extension)) {
dl($extension_soname) or die("Can't load extension $extension_fullname\n");
}

$fil='/var/www/html/tt/test.avi';
$frame = 6;
$time = time ();
$movie = new ffmpeg_movie($fil, 1);

$duration = $movie->getDuration();

if ( $duration > 6 ){
$minutes = floor($movie -> getDuration ()/ 60);
$seconds = $movie -> getDuration ()% 60 ;
}

echo 'File: <font color="red">' . $_SERVER [ 'DOCUMENT_ROOT' ] .'/tt/test.avi</font> longs ' . $duration . ' seconds<br />' ;

$img = $_SERVER [ 'DOCUMENT_ROOT' ]. '/tt/' . $time . '_' . $frame . '.jpg' ;

$ff_frame = $movie -> getFrame ( $frame );
if ( $ff_frame ){
$gd_image = $ff_frame -> toGDImage ();
if ( $gd_image ) {
imagepng ( $gd_image , $img );
imagedestroy ( $gd_image );
}
}

echo $minutes . ' min ' . $seconds . ' sec.<br />' ;

echo '<img src="' . $time . '_' . $frame . '.jpg" />' ;

$franecount = $movie->getFrameCount();
$framerate = $movie->getFrameRate();
$filename = $movie->getFilename();
$comment = $movie->getComment();

echo "<br /><br />number of frames in a movie or audio file.".$franecount."<br />";
echo "frame rate of a movie in fps".$framerate."<br />";
echo "path and name of the movie file or audio file.".$filename."<br />";
echo "comment field from the movie or audio file.".$comment."<br />";
?>
 


Заходим на http://YOUR_SERVER_IP/index.php и смотрим страницу с модулями, ищем ffmpeg, если есть смотрим http://YOUR_SERVER_IP/tt/test.php.
Если что-то не получилось посмотрите сначала в файл ошибок вашего web-сервера.

Литература:

http://linuxhostingsupport.net/blog/error-pix_fmt_rgba32-undeclared
http://itblog.su/php-ffmpeg-ustanovka-na-centos-5.html