В связи с тем, что официальная документация FastReport.Mono устарела, и даже не понятно к какой версии дистрибутива Debian она относится (могу предположить, что к 6 или младше), решил написать более-менее вменяемую инструкцию по установке демонстрационного Web-интерфейса для просмотра отчетов.
Проблема возникла из-за маячащей перспективы переезда одного из проектов, где использовался FastReport.Net, с Windows + Oracle на Linux + PostgreSQL. Кроме того, заинтересовала возможность реализации всего в виде микросервисов в контейнерах Docker. Увы — «гладко было на бумаге, да забыли про овраги»: пришлось столкнутся с рядом нюансов, которые постараюсь более-менее подробно описать и предложить возможные варианты решения проблем.
В процессе делал заметки-напоминалки для себя в wiki проекта, и лишь потом попытался все систематизировать. В итоге получилось много текста, публикацию попробую разделить, ориентировочно, на три части:
- Запуск демо-отчета
- Использование FastReport в контейнерах Docker
- Подключение к БД
N.B. Весь следующий текст это не пошаговое руководство к действию, а возможные варианты решения проблем (иногда более одного способа). По сему, советую сразу прочитать весь материал, а затем выбрать подходящий способ установки.
Введение
И так, первое, на что хотелось бы обратить внимание – имена пакетов и проблемы с зависимостями. Если вы планируете использовать Debian 8 (Jessie), то будьте готовы к необходимости ставить Mono из репозитория Mono-project или даже собирать из исходников. В официальных репозиториях Jessie отсутствует часть пакетов, например libapache2-mod-mono. Заниматься этим не стал, так что, все изыскания были проведены на Debian 9 (Stretch). Настоятельно не рекомендую устанавливать пакет с примерами ASP.Net — asp,net-examples, т.к. в процессе установки будет добавлен инклуд в конфиг Apache, содержащий единые настройки Mono для всех виртуальных хостов, так же будет добавлен универсальный алиас /samples.
Второе: при использовании конфигурационного файла виртуального хоста Apache из публикации в официальном блоге разработчиков, обратите внимание на то, что он написан для Apache 2.2 и не совсем подходит к Apache 2.4. Проблема кроется в изменении отсутствии Require all granted в секции …. Кроме того, возможны некоторые изменения настроек Mono: что-то можно опустить т.к. соответствует значениям «по умолчанию», а что-то может не подойти именно вам. В принципе, для запуска демо-проекта, можно опустить практически всё. И, конечно же, в зависимости от выбранной конфигурации, установка переменных окружения или прав доступа к файлам и каталогам.
Третьим, и очень интересным моментом, является то, что для правильной работы необходимо либо изменить структуру каталогов, не занимаясь тупой копипастой строчек из примера, а изучив еще один пост (почему авторы не объединили две записи в одну — для меня загадка). Либо установить переменную окружения MONO_PATH так, чтобы она смотрела в каталог с файлами FastReport.*.dll и поправить web.config.
Четвертый, и самый спорный и интересный момент – для работы FastReport.Web в некоторых случаях нужны иксы (X11). Например, демонстрационный проект со штрихкодами требует System.Windows.Forms. И, если при запуске сервера от имени пользователя, вошедшего через GUI, особых проблем нет, то в случаях запуска проекта через SSH, в Apache или Docker-контейнере потребуется настройка переменных окружения, а в случае контейнеров — еще и «проброска» X-сервера извне.
Пятым пунктом будет рассмотрен процесс сборки коннекторов для некоторых популярных СУБД. Это связано с тем, что с FastReport (как Windows, так и Mono-версии), плагины для использования СУБД поставляются в виде исходных текстов, а не готовых к употреблению библиотек. Придется собирать вручную.
Но обо всем по порядку. Предполагаю, что система уже установлена, и она не совсем пустая — в ней есть ваш любимый текстовый редактор и архиватор.
Начальная установка
Если верить официальному мануалу, то установка не должна занять много времени в все должно пройти гладко, через apt. Что же, приступим. Устанавливаем Mono, веб-сервер XSP, веб-сервер Apache и модуль, позволяющий запускать ASP.Net-приложения через Apache.
apt-get install mono-complete mono-xsp apache2 libapache2-mod-mono
Далее, скачиваем и распаковываем демонстрационный проект. Здесь и далее я специально буду использовать пути, отличные от /var/www. В первую очередь, это позволяет найти ошибки в конфигурации или даже в самом проекте. А во-вторых, размещение сторонних программных продуктов в /opt соответствует целевому назначению данного каталога.
mkdir –p /opt/fastreport/htdocs
# качаем
wget https://www.fastreport.ru/public_download/frmono_demo.zip -O /tmp/frmono_demo.zip
# распаковываем, копируем, запускаем
unzip /tmp/frmono_demo.zip –d /tmp/frmono.demo
cp –rp /tmp/frmono.demo/Demos/C#/Web/* /opt/fastreport/htdocs
cd /opt/fastreport/htdocs
xsp
Рис 1. Запуск XSP
XSP – легковесный веб-сервер для APS.Net, написан на C# и позволяет быстро и просто осуществлять тестирование простеньких приложений. Если верить документации и советам бывалых – к использованию в боевом окружении не рекомендован. По умолчанию, XSP слушает 9000 порт и все сетевые адаптеры (IP 0.0.0.0). Данная процедура покажет нам – работает ли в принципе хоть что-нибудь. Могу предположить, что получите какое-либо исключение. Увы, авторы такого, казалось бы, интересного инструмента для генерации отчетов, не позаботились об удобстве при установке демонстрационных материалов.
Рис. 2. Возможное сообщение об ошибке (картинка кликабельна)
Данная проблема связана с тем, что Mono не находит библиотеку FastReport.Web.dll. Причем, ошибка возникает даже если файл скопировать в htdocs. Я не специалист по .NET, и уж тем более по Mono. Да и ссылку на пост в блоге авторов, которую привел во вступлении, прочел не сразу (кстати, есть вопрос — почему на это не сделан акцент, например жирным шрифтом выделены имена файлов, а не каталог?). По сему, пришлось поломать голову. Первый возможный вариант решения – копирование DLL в текущий каталог и установка переменной окружения MONO_PATH:
cp /tmp/frmono.demo/FastReport.*.dll ./
export MONO_PATH=./
Но тут тоже поджидает неудача. Скорее всего, вы получили исключение, что неймспейс или тип FastReport.Utils не найден. Проблему можно решить – достаточно прописать FastReport.Mono.dll в web.config.
Рис. 3. Ошибка компиляции — не найден тип или неймспейс Utils (картинка кликабельна)
Добавляем зависимость – в секцию web.config прописываем следующую строку:
<add assembly="FastReport.Mono, Version=2017.1.8.0, Culture=neutral, PublicKeyToken=db7e5ce63278458c"/>
Номер версии и токен могут отличаться, на данный момент актуальны именно такие. Получить токен из dll можно так:
sn -T FastReport.Mono.dll
Проверить номер версии можно следующим образом:
monodis --assembly FastReport.Mono.dll | grep "Version"
Результатом всех наших мучений должно стать мало-мальски вменяемое отображение страницы с демонстрационным отчетом.
Рис. 4. Не совсем работающий пример
Увы, что-то пошло не так. Предполагалось, что в окне браузера будут штрихкоды, как на скриншоте в официальном мануале FastReport.Mono. У вас этой ошибки может и не быть, о причинах ее возникновения и способе устранения расскажу чуть ниже.
А пока вернемся к библиотекам. В процессе написания инструкции, был найден еще один способ решения проблемы с подключением FastReport.Web.dll и FastReport.Mono.dll (рисунки 2, 3), хотя, наверное, разработчики .NET так бы сделали сразу. Достаточно создать директорию htdocs/bin и переместить FastReport.Web.dll и FastReport.Mono.dll туда. Необходимость править web.config и изменять MONO_PATH отпадает, Mono все находит и исключений не кидает. Хорошо это или плохо – сложно сказать. В принципе, если все будет спрятано за фронтендом в лице Apache, то директорию с dll-ками можно прикрыть от посторонних глаз. Структура каталогов при таком решении изображена на рисунке 5.
Рис. 5. Дерево каталогов демонстрационного проекта
Использование System.Windows.Forms
Демонстрационный Web-отчет в списке зависимостей содержит System.Windows.Forms. Если вы заглядывали в web.config, то думаю обратили внимание на строку:
<add assembly="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
Если вы столкнулись с проблемой, изображенной на скриншоте 4 или в консоли увидели сообщение «No protocol specified», значит имеет место быть один из следующих вариантов:
- не установлен или не запущен Xorg
- X-сервер запущен, вы пытаетесь запускать XSP от суперпользователя
- X-сервер запущен, вы пытаетесь запускать XSP в сессии ssh
- X-сервер запущен, вы используете Apache, пользователь www-data не имеет нужных прав Используется Docker
В первом случае необходимо установить/запустить иксы. Варианты 2 и 3 в своей сути похожи, и проблема решается установкой переменных окружения DISPLAY, и, возможно, XAUTHORITY. С той лишь разницей, что если ОС была изначально установлена с графическим окружением, у пользователя переменная XAUTHORITY установлена и смотрит на файл ~/.Xauthority, а у root'а ее нет. В принципе, достаточно перед запуском XSP сделать следующее:
export DISPLAY=:0
Для root'а необходимо добавить:
export XAUTHORITY=/var/run/lightdm/root/:0
На самом деле, запускать что-либо от имени суперпользователя плохая идея, но если уж очень хочется… Кроме того, установка переменной XAUTHORITY еще пригодится при настройке Apache, чтобы разрешить пользователю www-data использовать X-сервер (актуальное, если в процессе установки Debian были выбраны пакеты графического окружения). В случае, если ОС изначально устанавливалась в минимальном варианте, все будет несколько отличатся, т.к. Xorg вполне возможно будет установлен без дисплей-менеджера. Или вообще не установлен.
Если вы столкнулись с необходимостью «завернуть» FastReport.Mono в контейнер и решили соблюдать принцип «1 сервис – 1 контейнер», то придется рядом создать контейнер с X-сервером и «пробросить» сокет между контейнерами. В качестве видеодрайвера придется использовать Dummy display driver. Такая настройка будет рассмотрена в одной из следующих частей руководства.
apt-get install xserver-xorg-video-dummy
Альтернативным вариантом для пользователей Linux/Unix может быть «проброска» X-сервера из ОС хоста (tcp или unix-сокет). Для получения такой возможности в MacOS необходимо установить XQuartz.
Настройка Apache
В принципе, настройка Apache 2.4 и mod_mono не требует каких-то особых хитростей. Если вы, вдруг, не последовали моему совету и установили пакет asp.net-examples, рекомендую после проверки работоспособности mod_mono закомментировать следующую строку в
/etc/apache2/mods-available/mod_mono.conf:
Include /etc/mono-server4/mono-server4-hosts.conf
В противном случае, на все ваши виртуальные хосты будет прибит алиас /samples, по которому будут открываться собственно те самые примеры использования ASP.Net. Кроме того, Apache может в логах и при перезапуске ругаться на то, что mod_mono уже загружен. Это связано с тем, что подгружается два модуля — mod_mono и mod_mono_auto (для автоматического деплоя приложений). Mod_mono_auto можно смело отключить:
a2dismod mod_mono_auto && service apache2 restart
Конфигурационный файл виртуального хоста из официальной документации избыточен по настройкам и в некоторых местах не актуален. Минимально необходимый конфиг можно посмотреть под спойлером.
Listen 8081
<VirtualHost *:8081>
DocumentRoot "/opt/fastreport/htdocs"
<IfModule mod_mono.c>
MonoUnixSocket FrSite /tmp/.mod_mono_server
MonoServerPath FrSite /usr/bin/mod-mono-server4
# Если будем хранить библиотеки в директории htdocs/bin - последнюю часть пути можно опустить
# В противном случае надо оставить /opt/fastreport/htdocs или заменить на путь
# к каталогу с FastReport.*.dll
MonoPath FrSite /usr/lib/mono/4.5:/usr/lib:/usr/lib/mono/4.0:/opt/fastreport/htdocs
AddMonoApplications FrSite "/:/opt/fastreport/htdocs"
MonoAutoApplication Disabled
MonoDocumentRootDir /opt/fastreport/htdocs
MonoDebug false
MonoSetEnv FrSite DISPLAY=:0;HOME=/opt/fastreport
AddHandler mono .aspx .ascx .asax .ashx .config .cs .asmx .axd
</IfModule>
<Directory "/opt/fastreport/htdocs">
Require all granted
Options Indexes FollowSymLinks MultiViews
AllowOverride All
<IfModule mod_mono.c>
SetHandler mono
MonoSetServerAlias FrSite
DirectoryIndex Default.aspx
</IfModule>
</Directory>
# Если мы используем каталог bin для подключаемых dll
# В противном случае можно удалить
<Directory "/opt/fastreport/htdocs/bin">
Require all denied
</Directory>
</VirtualHost>
Собственно, помещаем все в /etc/apache2/sites-available/001-mono.conf при помощи любимого текстового редактора, включаем сайт и перезапускаем Apache:
a2ensite 001-mono && service apache2 restart
Разбирать весь конфиг не имеет глубокого смысла, однако на одной строке хотелось бы остановиться подробнее:
MonoSetEnv FrSite DISPLAY=:0;HOME=/opt/fastreport
Это очень знатный костыль, который позволяет решить сразу 2 проблемы. Одну из них я уже описывал в разделе, посвященному System.Windows.Forms — приложению нужно указать DISPLAY. Второй же момент связан с тем, что в процессе компиляции и исполнения приложения, используются директории ~/.local и ~/.mono, а у пользователя www-data, от которого работает Apache, домашняя директория — /var/www. Я посчитал, что не стоит мусорить по всей системе. В принципе — работает. Конечно, можно было бы попробовать изменить пользователя и группу для конкретно этого виртуального хоста, но не взлетело. Насколько я понял, mod_mono запускает сервер от пользователя Apache и при попытке использования mpm_itk ничего не взлетело. Вполне возможно, что проблема может быть решена использованием FastCGI, но не пробовал, на истинность не претендую.
Последним штрихом остается дать доступ пользователю www-data к X-серверу. И тут нам пригодится возможность установки XAUTHORITY для суперпользоватля.
export XAUTHORITY=/var/run/lightdm/root/:0
export DISPLAY=:0
xhost + local:www-data
service apache2 restart
Хотел бы обратить внимание на то, что изменения, внесенные при вызове xhost будут активны только до выключения/перезагрузки. Если вы используете lightdm, то имеет смысл обернуть данную конструкцию в скрипт и установить его автозапуск, добавив строку display-setup-script=/путь/к/скрипту.sh в /etc/lightdm/lightdm.conf. В качестве альтернативного варианта, можно изменить /etc/X11/xinit/xinitrc.
Рис. 6. Работоспособный пример через Apache 2.4
Автор: DzmitryT