Category Archives: Linux

Настройка сервера с нуля на примере VPS от Hetzner’а

Hetzner.de – выбираем сервер

Итак, закажем и настроим свой собственный VPS. Заходим на https://www.hetzner.de/, в верхнем меню выбираем VServer (виртуальный сервер). Давайте выберем средний по цене, но вроде как с неплохими характеристиками: vServer CX30

Обратим внимание на цену: на немецком он предлагается за 14,16€ / Monat (14,16 евро в месяц), а после переключения на русский язык или USA: € 11.90 per month / 11,90€ / месяц.

Что за? Да, немцы своим дороже что ли продают? У них денег, видимо больше. Да ладно, переведём евро на рубли, сейчас Яндекс показывает 63,57 руб./ 1EUR – курс ЦБ РФ на 28/12/2016. Округлим до 65, получается сумма менее 1.000 руб: 11,90€ * 65 руб. = 773.50 руб/месяц.

Я думаю, неплохо, особенно после того как посмотрим на предлагаемую конфигурцию сего чуда:
Benefits: 2 vCores, RAM 4 GB RAM, SSD 100 GB, Connection: 1 Gbit/s NIC, Traffic: 8 TB, Snapshots: 3. Что в переводе на русский означает 2 ядра (виртуальных), 4 гига оперативки, диск на 100 гигов (SSD), скорость связи 1 Гигабит/секунда, предел трафика – 8 Терабайт. Сразу замечу, что в комментарии указано, что при превышении предела трафика за месяц скорость подключения снизится до 10 Мегабит в секунду, но сервер по прежнему будет доступен. Да, и ещё в комплектацию входит поддержка до 3 снэпшотов, так что при желании можно откатиться.

Заказываем сервер

Ну что, друзья, неплохо за такие деньги или как? ОК, поехали! Вперед, без сомнений, этот сервер будет наш. Нажимаем кнопочку “Order now” (“Заказать” – да, сайт Hetzner.de поддерживает русский в том числе, да вообще много языков, но вот насчёт самой тех.поддержки не уверен, думаю, английским обойдёмся если что). А сама админка сервера (https://robot.your-server.de/server) у меня на английском, я честно говоря, доволен и так.

Далее нам предстоит выбрать систему из списка:

Operating systems without pre-installed control panel

  • CentOS 6.8 minimal
  • CentOS 7.2 minimal
  • Debian 8.6 LAMP
  • Debian 8.6 minimal
  • openSUSE 42.1 minimal
  • Ubuntu 16.04.1 LTS minimal
  • Ubuntu 16.10 minimal
  • Windows Server 2012 R2 Datacenter Edition (Price (monthly): € 130.25 / Setup (once): € 0.00)
  • Windows Server 2012 R2 Standard Edition (Price (monthly): € 21.01 / Setup (once): € 0.00)

Operating systems with pre-installed control panel

  • CentOS 7.2 + cPanel
  • CentOS 7.2 + Plesk
  • Debian 8.6 + Plesk
  • Ubuntu 16.04.1 LTS + Plesk
  • Windows Server 2012 R2 Datacenter Edition + Plesk (Price (monthly): € 130.25 / Setup (once): € 0.00)
  • Windows Server 2012 R2 Standard Edition + Plesk (Price (monthly): € 21.01 / Setup (once): € 0.00)

То есть два списка – без контроль-панели и с ней (cPanel/Plesk).

Ребята, мы выбираем – Ubuntu 16.10 minimal без всяких панелей. Это минимальная система, в ней как я понял, дополнительно будут установлены основные системные утилиты (coreutils) и SSH. Как раз то, что нам нужно. Всё остальное – NGINX/PHP/MYSQL/POSTFIX/DOVECOT/PUREFTPD/SpamAssassin/FAIL2BAN и т.д. и т.п. (по-русски etc.) мы установим сами, своими собственными ручками, тем более это не так уж и сложно и не так уж и долго, в частности благодаря APT‘у.

На нашем сервере будет работать 3-4 сайта на NGINX/PHP-FPM, крутится радио и, возможно, экспериментальный сайтик на node.js. Также мы поставим FFMPEG и ImageMagic для беспрепятственной обработки видео/аудио/графики.

Итак, далее идёт опция – выбрать SSH-доступ ч/з пароль или через ключи, я выбрал пароль, но это дело вкуса, тем более потом всегда можно всё поменять.

Потом, если у Вас нет аккаунта на Hetzner.de, Вам предложат его создать, ничего особенного, доволньо небольшая форма, и опосля предложат ввести данные своей банковской карты. Так как я этому сайту доверяю (кто не знает Hetzner.de?) я без страха ввожу все нужные данные и… получаю сервер в свои руки.

Рабочая среда в Windows 10

Мне на почту пришло письмо буквально через 5-10 минут, что сервер готов к работе, здесь же мне указали рутовый пароль и ip-адрес нашего сервера. Итак, открываем свой любимый SSH-клиент, например, Putty и поехали!

Да, кстати, в своей Windows 10 я использую связку WinSCP + Putty. То есть захожу на файловую систему сервера под рутом через WinSCP по SFTP протоколу, здесь же могу копировать/удалять/править в виндовом редакторе (мой любимый сейчас AkelPad) любой файл, а нажав на кнопочку Ctrl+P (Open session in PuTTY) я моментально, без ввода пароля, попадаю в консоль PuTTY (конечно, всё это надо настроить в WinSCP предварительно, что делается буквально в несколько кликов мышки).

Настройка DNS

Лично я использую бесплатный Hurricane Electric Free DNS Management – https://dns.he.net/
А Hetzner.de предлагает подобную вещь за:

Nameserver Robot

    Administer DNS entries

more information...
Price (once): € 15.97
For Dedicated Root Server and vServer customers free of charge

Это 15,97 евро * 65 рублей = 1038,05 рублей. Это разовая оплата. Чем он лучше бесплатного? На бесплатный нельзя полагаться на 100%, хотя мы работаем с Hurricane Electric несколько лет и ни разу не было проблем (в отличие от https://entrydns.net/, который часто глючил, а потом стал просить денег, хоть и не больших).

Но тут нам раздумывать нечего – видите надпись – Free of charge for dedicated root server and vServer customers? Да, для нашего виртульаного сервера он должен быть бесплатным. Но при заходе на https://robot.your-server.de/ мы нигде не видим ссылку на что-то подобное NS/DNS. Оказывается, его просто надо заказать дополнительно – заходим по ссылкам: Ordering – Domain Administration – Nameserver Robot – Order Product и видим:

Shopping cart
  	  	Unit price 	Total price 	 
  	  	Monthly 	Setup 	Monthly 	Setup 	 
1 x 	Nameserver Robot 	€ 0.00 	€ 0.00 	€ 0.00 	€ 0.00 	
Total: 	€ 0.00 	€ 0.00 	 

Да, везде нули, в данном случае это хорошо, он для нас действительно вроде как бесплатен.

Но, повторяюсь, я использую Hurricane Electric, поэтому здесь не стал заказывать.

Как настроить начальные и самые необходимые NS записи для сайтов рассказано здесь, на этом блоге (на примере Hurricane Electric Free DNS Management) – http://atzar.ru/hurricane-electric-free-dns-management/. На Hetzner’е, думаю, настравается всё подобным образом. Настраиваем всё под наш новый ip сервера.

Первые шаги

Итак, смотрим, что уже у нас в действительности есть, держа в уме, что всё же это виртуалка, а не полноценный сервер. Но у нас пока нет десятков тысяч – миллионов клиентов, чтобы держать полноценный сервер или кластер таких серверов.
Все команды я будут выполнять от рута, так как у меня нет паранойи по этому поводу, ты через sudo сможешь накосячить также как и не через sudo. Да ладно, это дело в куса а не принципа.
Нас встречает приглашние вида:
root@Ubuntu-1610-yakkety-64-minimal ~ #

FQDN

Заздадим Fully Qualified Domain Name:
# hostname beotiger
# echo beotiger > /etc/hostname
# vim /etc/hosts
ip-адрес нашего сервера site2.ru

Теперь перелогинимся и получим приглашение root@beotiger ~ #

Итак, версия:

# uname -a
Linux beotiger 4.8.0-32-generic #34-Ubuntu SMP Tue Dec 13 14:30:43 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

# cat /etc/issue
Ubuntu 16.10 \n \l

Сколько памяти свободно:

# free -h
total used free shared buff/cache available
Mem: 3.9G 218M 2.8G 17M 841M 3.4G
Swap: 0B 0B 0B

Дисковое пространство:

# df -h
Filesystem Size Used Avail Use% Mounted on
udev 2.0G 0 2.0G 0% /dev
tmpfs 396M 8.7M 387M 3% /run
/dev/sda1 94G 2.1G 87G 3% /
tmpfs 2.0G 0 2.0G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 2.0G 0 2.0G 0% /sys/fs/cgroup
tmpfs 396M 0 396M 0% /run/user/0

Итак, видим, что наша пока пустая система сжирает 218Мегабайт оперативки и 2.1Гиг нашего диска. Посмотрим, что будет после установки всех нужных нам сервисов! Для удобного просмотра состояние системы и процессов можно установить htop:

# apt install htop

Язык и timezone

Лично я предпочитаю английский в документации, сказывается давняя паранойя о плохом переводе. Поэтому локаль не меняю. А время всё же поменяю на московское, а то в логах буду путаться (я живу по московскому времени):

# apt install tzdata
# dpkg-reconfigure tzdata

Выбираем пояс Europe/Moscow, и ребутнемся, вспомним времена Win98 (чтобы все наши уже запущенные службы стали использовать новый часовой пояс в логах и т.п.):

# reboot

Синхронизация времени

Внимание! NTP не нужен, если есть timesyncd и мы не собираемся выступать в роли ntpd сервера. Пакет: systemd: /lib/systemd/systemd-timesyncd
# timedatectl status
Local time: Fri 2016-12-30 12:13:22 MSK
Universal time: Fri 2016-12-30 09:13:22 UTC
RTC time: Fri 2016-12-30 09:13:22
Time zone: Europe/Moscow (MSK, +0300)
Network time on: yes
NTP synchronized: yes
RTC in local TZ: no

Строка NTP synchronized: yes говорит о том, что время синхронизируется успешно.

Устанавливаем LEMP-стек: NGINX + PHP 7.0 + MySQL

LAMP: Linux Apache MySQL PHP – минимальная готовая среда веб-разработки. Linux у нас есть, Apache мы поменяем на Nginx. Т.е. LAMP -> LEMP (Linux Nginx MySQL PHP). Итак, ставим, настраивать будем позже:

NGINX

NGINX самая простая и мощная вещь, как раз то, что я люблю больше всего:

# apt install nginx

Всё, у нас есть рабочий сервер. Уже можно зайти на http://ip-нашего-сервера и узреть стандартную дефолтную страницу nginx. Дефолтная папка сайта /var/www/html. Мы её трогатиь не будем, когда поставим PHP/MySQL, займёмся детальной настройкой и связкой NGINX+PHP7 (напомню, будем добавлять несколько сайтов)

Текущая версия nginx:

# nginx -v
nginx version: nginx/1.10.1 (Ubuntu)

Посмотреть текущие модули nginx (где-то видел хак на stackoverflow):

# 2>&1 nginx -V | tr -- - '\n' | grep _module
http_ssl_module
http_stub_status_module
http_realip_module
http_auth_request_module
http_addition_module
http_dav_module
http_geoip_module
http_gunzip_module
http_gzip_static_module
http_image_filter_module
http_v2_module
http_sub_module
http_xslt_module
stream_ssl_module
mail_ssl_module

В стандартном nginx-пакете есть только самые необохдимые модули. Если Вам нужны допонлительные модули, например, MP4, совсем не обязательно перекомпилировать nginx с сорцов.
Добавить модули в nginx можно так (ещё не пробовал):

# apt install nginx-extras

Возможная конфигурация с использованием модуля mp4:

location /video/ {
mp4;
mp4_buffer_size 1m;
mp4_max_buffer_size 5m;
mp4_limit_rate on;
mp4_limit_rate_after 30s;
}

Смотрим, что содержиться в nginx-extras:

# apt show nginx-extras
Package: nginx-extras
Version: 1.10.1-0ubuntu1.2
Priority: optional
Section: universe/httpd
Source: nginx
Origin: Ubuntu
Maintainer: Ubuntu Developers
Original-Maintainer: Kartik Mistry
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 1,886 kB
Provides: httpd, httpd-cgi, nginx
Depends: nginx-common (= 1.10.1-0ubuntu1.2), perl (>= 5.22.2-3), perlapi-5.22.2, libc6 (>= 2.14), libexpat1 (>= 2.0.1), libgd3 (>= 2.1.0~alpha~), libgeoip1, libluajit-5.1-2, libpam0g (>= 0.99.7.1), libpcre3, libperl5.22 (>= 5.22.2), libssl1.0.0 (>= 1.0.2~beta3), libxml2 (>= 2.7.4), libxslt1.1 (>= 1.1.25), zlib1g (>= 1:1.1.4)
Suggests: nginx-doc (= 1.10.1-0ubuntu1.2)
Conflicts: nginx-core, nginx-full, nginx-light
Breaks: nginx (<< 1.4.5-1) Homepage: http://nginx.net Download-Size: 630 kB APT-Sources: http://mirror.hetzner.de/ubuntu/packages yakkety-updates/universe amd64 Packages Description: nginx web/proxy server (extended version) Nginx ("engine X") is a high-performance web and reverse proxy server created by Igor Sysoev. It can be used both as a standalone web server and as a proxy to reduce the load on back-end HTTP or mail servers. . This package provides a version of nginx with the standard modules, plus extra features and modules such as the Perl module, which allows the addition of Perl in configuration files. . STANDARD HTTP MODULES: Core, Access, Auth Basic, Auto Index, Browser, Empty GIF, FastCGI, Geo, Limit Connections, Limit Requests, Map, Memcached, Proxy, Referer, Rewrite, SCGI, Split Clients, UWSGI. . OPTIONAL HTTP MODULES: Addition, Auth Request, Charset, WebDAV, FLV, GeoIP, Gunzip, Gzip, Gzip Precompression, Headers, HTTP/2, Image Filter, Index, Log, MP4, Embedded Perl, Random Index, Real IP, Secure Link, SSI, SSL, Stream, Stub Status, Substitution, Thread Pool, Upstream, User ID, XSLT. . MAIL MODULES: Mail Core, Auth HTTP, Proxy, SSL, IMAP, POP3, SMTP. . THIRD PARTY MODULES: Auth PAM, Cache Purge, DAV Ext, Echo, Fancy Index, Headers More, Embedded Lua, HTTP Push, HTTP Substitutions, Upload Progress, Upstream Fair Queue.

Много всего, нужно ли оно нам сейчас?! Как подключать/отключать нужные модули при запуске сервера/службы?

PHP 7.0

Конечно, будем стаить семёрку. По заявлению многих, она намного быстрее пятёрки. Не знаю, не проверял, но охотно верю! Заметьте, что пакет PHP7.0, который описывается так:

php7.0/yakkety,yakkety,yakkety,yakkety 7.0.8-3ubuntu3 all
server-side, HTML-embedded scripting language (metapackage)

предложит нам поставить apache, я не знаю почему, что в головах творится у этих собирателей пакетов под Юбунту? Сами смотрите:

# apt install php7.0
The following additional packages will be installed:
  apache2 apache2-bin apache2-data apache2-utils libapache2-mod-php7.0 libapr1
  libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap liblua5.1-0 php-common
  php7.0-cli php7.0-common php7.0-json php7.0-opcache php7.0-readline psmisc
  ssl-cert
 
The following NEW packages will be installed:
  apache2 apache2-bin apache2-data apache2-utils libapache2-mod-php7.0 libapr1
  libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap liblua5.1-0 php-common php7.0
  php7.0-cli php7.0-common php7.0-json php7.0-opcache php7.0-readline psmisc
  ssl-cert
0 upgraded, 19 newly installed, 0 to remove and 0 not upgraded.
Need to get 5,066 kB of archives.
After this operation, 20.6 MB of additional disk space will be used.
Do you want to continue? [Y/n]n [Aborted]

Nooooooooo, тут нажимаем n, нет, nicht, nope, ни в коем случае. Вы что творите, сборщики пакетов для Убунты?

Пакет php7.0-fpm:

php7.0-fpm/yakkety,yakkety 7.0.8-3ubuntu3 amd64
server-side, HTML-embedded scripting language (FPM-CGI binary)

# apt install php7.0-fpm
	Reading package lists... Done
	Building dependency tree
	Reading state information... Done
	The following additional packages will be installed:
	  php-common php7.0-cli php7.0-common php7.0-json php7.0-opcache php7.0-readline
	  psmisc
	Suggested packages:
	  php-pear
	The following NEW packages will be installed:
	  php-common php7.0-cli php7.0-common php7.0-fpm php7.0-json php7.0-opcache
	  php7.0-readline psmisc
	0 upgraded, 8 newly installed, 0 to remove and 0 not upgraded.
	Need to get 3,570 kB of archives.
	After this operation, 14.3 MB of additional disk space will be used.
	Do you want to continue? [Y/n] Y
 
	Creating config file /etc/php/7.0/cli/php.ini with new version
	Setting up php7.0-fpm (7.0.8-3ubuntu3) ...
 
	Creating config file /etc/php/7.0/fpm/php.ini with new version
	Created symlink /etc/systemd/system/multi-user.target.wants/php7.0-fpm.service → /lib/systemd/system/php7.0-fpm.service.

ИЗ: https://php-fpm.org/
PHP-FPM (FastCGI Process Manager) альтернатива PHP FastCGI со множеством новых полезных возможностей, подходящих для сайтов любых размеров, особенно для загруженных сайтов. Включают: Адаптивный запуск процессов! Статистика! These features include: Adaptive process spawning (NEW!) Basic statistics (ala Apache's mod_status) (NEW!)

Итак, мы видим, что установились основные пакеты PHP7.0 - common, cli (для вызова PHP из командной строки), fpm - как раз то, что нам нужно для связи с NGINX, нашим вебсервером, json - полезная штука, мы её применяем практически во всех наших проектах, особенно основанных на AJAX, opcache - кэширование, readline - возможность проводить с PHP сессию типа интерактивного шелла, подробнее см. здесь: http://php.net/manual/en/features.commandline.interactive.php

Доустановим некоторые наиболее важные и нужные PHP-пакеты, часто используемые не только в наших проектах:

# apt install php7.0-curl php7.0-gd php7.0-mbstring php7.0-mcrypt php7.0-mysql php7.0-sqlite3
...
The following additional packages will be installed:
  libcurl3 libmcrypt4
Suggested packages:
  libmcrypt-dev mcrypt
The following NEW packages will be installed:
  libcurl3 libmcrypt4 php7.0-curl php7.0-gd php7.0-mbstring php7.0-mcrypt php7.0-mysql
  php7.0-sqlite3

curl - общение с сетью из PHP ч/з удобный CURL API, gd - рисование графических примитов и текста, mbstring - поддержка мультибайтовых строк, mcrypt - криптование, кому оно сейчас не треба)), mysql и sqlite3 - именно эти БД я использую в своих проектах, вам могут понадобиться другие БД, например pgsql или sybase. Вообще список доступных пакетов PHP 7 можно посмотреть например так:

# apt search php7
Sorting... Done
Full Text Search... Done
libapache2-mod-php7.0/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  server-side, HTML-embedded scripting language (Apache 2 module)

libphp7.0-embed/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  HTML-embedded scripting language (Embedded SAPI library)

php-all-dev/yakkety,yakkety,yakkety,yakkety 1:44 all
  package depending on all supported PHP development packages

php-symfony-polyfill-php70/yakkety,yakkety,yakkety,yakkety 1.2.0-1 all
  Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions

php7.0/yakkety-updates,yakkety-updates,yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 all
  server-side, HTML-embedded scripting language (metapackage)


php7.0-bcmath/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  Bcmath module for PHP

php7.0-bz2/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  bzip2 module for PHP

php7.0-cgi/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  server-side, HTML-embedded scripting language (CGI binary)

php7.0-cli/yakkety-updates,yakkety-updates,now 7.0.13-0ubuntu0.16.10.1 amd64 [installed,automatic]
  command-line interpreter for the PHP scripting language

php7.0-common/yakkety-updates,yakkety-updates,now 7.0.13-0ubuntu0.16.10.1 amd64 [installed,automatic]
  documentation, examples and common module for PHP

php7.0-curl/yakkety-updates,yakkety-updates,now 7.0.13-0ubuntu0.16.10.1 amd64 [installed]
  CURL module for PHP

php7.0-dba/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  DBA module for PHP

php7.0-dev/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  Files for PHP7.0 module development

php7.0-enchant/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  Enchant module for PHP

php7.0-fpm/yakkety-updates,yakkety-updates,now 7.0.13-0ubuntu0.16.10.1 amd64 [installed]
  server-side, HTML-embedded scripting language (FPM-CGI binary)

php7.0-gd/yakkety-updates,yakkety-updates,now 7.0.13-0ubuntu0.16.10.1 amd64 [installed]
  GD module for PHP

php7.0-gmp/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  GMP module for PHP

php7.0-imap/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  IMAP module for PHP

php7.0-interbase/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  Interbase module for PHP

php7.0-intl/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  Internationalisation module for PHP

php7.0-json/yakkety-updates,yakkety-updates,now 7.0.13-0ubuntu0.16.10.1 amd64 [installed,automatic]
  JSON module for PHP

php7.0-ldap/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  LDAP module for PHP

php7.0-mbstring/yakkety-updates,yakkety-updates,now 7.0.13-0ubuntu0.16.10.1 amd64 [installed]
  MBSTRING module for PHP

php7.0-mcrypt/yakkety-updates,yakkety-updates,now 7.0.13-0ubuntu0.16.10.1 amd64 [installed]
  libmcrypt module for PHP

php7.0-mysql/yakkety-updates,yakkety-updates,now 7.0.13-0ubuntu0.16.10.1 amd64 [installed]
  MySQL module for PHP

php7.0-odbc/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  ODBC module for PHP

php7.0-opcache/yakkety-updates,yakkety-updates,now 7.0.13-0ubuntu0.16.10.1 amd64 [installed,automatic]
  Zend OpCache module for PHP

php7.0-pgsql/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  PostgreSQL module for PHP

php7.0-phpdbg/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  server-side, HTML-embedded scripting language (PHPDBG binary)

php7.0-pspell/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  pspell module for PHP

php7.0-readline/yakkety-updates,yakkety-updates,now 7.0.13-0ubuntu0.16.10.1 amd64 [installed,automatic]
  readline module for PHP

php7.0-recode/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  recode module for PHP

php7.0-snmp/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  SNMP module for PHP

php7.0-soap/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  SOAP module for PHP

php7.0-sqlite3/yakkety-updates,yakkety-updates,now 7.0.13-0ubuntu0.16.10.1 amd64 [installed]
  SQLite3 module for PHP

php7.0-sybase/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  Sybase module for PHP

php7.0-tidy/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  tidy module for PHP

php7.0-xml/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  DOM, SimpleXML, WDDX, XML, and XSL module for PHP

php7.0-xmlrpc/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  XMLRPC-EPI module for PHP

php7.0-xsl/yakkety-updates,yakkety-updates,yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 all
  XSL module for PHP (dummy)

php7.0-zip/yakkety-updates,yakkety-updates 7.0.13-0ubuntu0.16.10.1 amd64
  Zip module for PHP

php7cc/yakkety,yakkety 1.1.0-1 amd64
  command line tool to detect PHP 7 incompatible code

MySQL

Кто-то ставит MariaDB, возможно, ожидая подвоха от Oracle, но я как-то прикипел к MySQL:


# apt install mysql-server
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
libaio1 libcgi-fast-perl libcgi-pm-perl libencode-locale-perl libevent-core-2.0-5
libfcgi-perl libhtml-parser-perl libhtml-tagset-perl libhtml-template-perl
libhttp-date-perl libhttp-message-perl libio-html-perl liblwp-mediatypes-perl
libtimedate-perl liburi-perl mysql-client-5.7 mysql-client-core-5.7 mysql-common
mysql-server-5.7 mysql-server-core-5.7
Suggested packages:
libdata-dump-perl libipc-sharedcache-perl libwww-perl mailx tinyca
The following NEW packages will be installed:
libaio1 libcgi-fast-perl libcgi-pm-perl libencode-locale-perl libevent-core-2.0-5
libfcgi-perl libhtml-parser-perl libhtml-tagset-perl libhtml-template-perl
libhttp-date-perl libhttp-message-perl libio-html-perl liblwp-mediatypes-perl
libtimedate-perl liburi-perl mysql-client-5.7 mysql-client-core-5.7 mysql-common
mysql-server mysql-server-5.7 mysql-server-core-5.7
0 upgraded, 21 newly installed, 0 to remove and 0 not upgraded.
Need to get 20.3 MB of archives.
After this operation, 172 MB of additional disk space will be used.

Твикать mysql пока не будем, если нагрузки будут большими, тогда пусть голова болит.

Связываем Nginx с PHP, создаём сайты

Итак, мы установили полный стек LEMP, теперь будем создавать сайты, создадим 3 сайта, остальные добавляем по подобию.

Названия и адреса наших сайтов:
1. site.ru
2. site.org
3. site.com

Для каждого сайта создадим в каталоге /var/www одноименные с именем сайта папки: site.ru site.org site.com. В каждой из этих папок создадим три подпапки:

  • tmp - для сессий и загрузок файлов
  • log - для логов nginx
  • web - для www данных (само содержимое сайта)
cd /var/www
mkdir -p site.ru/{tmp,web,log}
mkdir -p site.org/{tmp,web,log}
mkdir -p site.com/{tmp,web,log}

Также для каждого сайта будем создавать своего юзера с именам web1, web2, web3 и т.д. (при добавлении 4-го сайта создадим юзера web4, см. ниже). для каждого юзера будем использовать группу www-data.

Итак, добавляем пользователей и устанавливаем права доступа на соотв. папки. Все команды напомню осуществляем под root'ом:

useradd -m -d /var/www/site.ru -s $(which bash) -G www-data web1
useradd -m -d /var/www/site.org -s $(which bash) -G www-data web2
useradd -m -d /var/www/site.com -s $(which bash) -G www-data web3
 
cd /var/www
chown web1:www-data -R site.ru
chown web2:www-data -R site.org
chown web3:www-data -R site.com
 
passwd web1
passwd web2
passwd web3

Запомним пароли для пользователей web1, web2 и web3, они пригодятся нам далее для доступа к сайтам через FTP (см. далее по тексту).

PHP конфиг

Создадим конфигурационные файлы PHP-FPM для каждого юзера/сайта. Каждый сайт у нас будет обслуживаться своими PHP-FPM процессами, чтобы распределить нагрузку по всем сайтам. Названия конф файлов web[1..3].conf, они находятся в папке /etc/php/7.0/fpm/pool.d, PHP-FPM при запуске подключает всё оттуда. Итак, пример конфигурации для сайта site.ru (юзера web1):

cd /etc/php/7.0/fpm/pool.d
vim web1.conf

Содержимое web1.conf:

[web1]

listen = /run/php/php7.0-fpm1.sock
listen.owner = web1
listen.group = www-data
listen.mode = 0660

user = web1
group = www-data

pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 5
pm.max_requests = 0

chdir = /

php_admin_value[open_basedir] = /var/www/site.ru/web:/var/www/site.ru/tmp
php_admin_value[session.save_path] = /var/www/site.ru/tmp
php_admin_value[upload_tmp_dir] = /var/www/site.ru/tmp
php_admin_value[sendmail_path] = "/usr/sbin/sendmail -t -i"

security.limit_extensions = .php .html

Отметьте параметры:

listen = /run/php/php7.0-fpm1.sock - указываем на каком сокете будет слушать процесс PHP-FPM, он нам пригодится для настройки NGINX (см. ниже).

listen.owner = web1
listen.group = www-data - владелец/группа прав доступа к сокету

user = web1
group = www-data - владелец/группа запущенного процесса при подключении к сокету

php_admin_value[open_basedir] - указываем, в какие папки будет иметь доступ владелец процесса
php_admin_value[session.save_path] - указываем, в какой папке будут храниться сессии
php_admin_value[upload_tmp_dir] - указываем, в какую папку будут скачиваться файлы (upload)
php_admin_value[sendmail_path] - команда отправки почты, иcпользуемая функцией PHP mail. Настройкой почты мы займёмся чуть позже.

Для остальных двух сайтов - копируем файл web1.conf и поменяем юзера (web1 -> web2 -> web3), сокет - /run/php/php7.0-fpm1.sock -> /run/php/php7.0-fpm2.sock -> /run/php/php7.0-fpm3.sock и папку site.ru -> site.org -> site.com

cd /etc/php/7.0/fpm/pool.d
cp web1.conf web2.conf
vim web2.conf
cp web2.conf web3.conf
vim web3.conf

Настраиваем NGINX

Настройки сайтов хранятся в папке /etc/nginx/sites-available - доступные сайты. Чтобы сделать сайт активным и видимым nginx на него делают мягкую ссылку (симлинк) отсюда в папку /etc/nginx/sites-enabled - активные сайты.

Итак, заходим в папку /etc/nginx/sites-available и создаём файл для настроек первого сайта. Имя файла конечно же может быть любым, мы будем делать имена файлов в виде имён сайтов с добавления суффикса .vhost, чтобы показать, что это настройки виртуального хоста. А симлинки будем назвать по имени используемого пользователя, чтобы видеть, каким именно пользователем мы используем данный сайт. Эта информация может пригодится, например, ч/з полгода, если мы давно не будем заглядывать сюда и у нас вылетит из головы, каких пользователей под какие сайты мы задавали - в этом случае будет не обязательно копаться в файлах настроек Nginx и PHP. Итак, приступим:

cd /etc/nginx/sites-available/
vim site.ru.vhost
ln -s site.ru.vhost /etc/nginx/sites-enabled/web1

Полное содержимое файла site.ru.vhost:

server {
        listen *:80;
        server_name site.ru www.site.ru;
        root   /var/www/site.ru/web;

        index index.html index.php;

        error_log /var/www/site.ru/log/error.log;
        access_log /var/www/site.ru/log/access.log combined;

        location ~ /\. {
            deny all;
            access_log off;
            log_not_found off;
        }

        location = /favicon.ico {
            log_not_found off;
            access_log off;
        }

        location = /robots.txt {
            allow all;
            log_not_found off;
            access_log off;
        }

        location ~* \.(js|css|png|jpg|jpeg|gif|svg)$ {
            expires max;
            # log_not_found off;
				}

        location ~ \.(php|html)$ {
            try_files /d58f8ccd9bffa83ebec930554209111f.htm @php;
        }

        location @php {
            try_files $uri =404;
            include /etc/nginx/fastcgi_params;
            fastcgi_pass unix:/run/php/php7.0-fpm1.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_intercept_errors on;
        }
}

Бегло пробежимся по настройкам. Итак,

root /var/www/site.ru/web;

как мы и говорили вначале, корень сайтов будет лежать в папке web.

location ~ /\. {
deny all;
access_log off;
log_not_found off;
}

Этот блок говорит о том, чтобы закрыть доступ ко всем файлам и папкам, начинающимся с точки (`.`). Если вам это не нужно, этот блок можно удалить.

location @php {
try_files $uri =404;
include /etc/nginx/fastcgi_params;
fastcgi_pass unix:/run/php/php7.0-fpm1.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors on;
}

Этот блок связывает NGINX с PHP-FPM ч/з сокет /run/php/php7.0-fpm1.sock - именно этот сокет мы задавали в web1.conf в качестве параметра для listen.

Остальные сайты делаем по образу и подобию site.ru.vhost - копируем, меняем в файле имя сервера и корневой путь к сайту (параметры server_name и root), не забываем исправить пути в error_log и access_log, и главное - не забудем указать другой сокет в параметре fastcgi_pass - это будет unix:/run/php/php7.0-fpm2.sock для site.org и unix:/run/php/php7.0-fpm3.sock для сайта site.com. После создания файлов в папке sites-available делаем на них симлинки в папку sites-enabled:

cd /etc/nginx/sites-available/
cp site.ru.vhost site.org.vhost
vim site.org.vhost
ln -s site.org.vhost /etc/nginx/sites-enabled/web2
cp site.ru.vhost site.com.vhost
vim site.com.vhost
ln -s site.com.vhost /etc/nginx/sites-enabled/web3

После создания и каждого изменения конфигурационых файлов следует перезапускать соотв. службу. Мы меняли конфиги для PHP-FPM и NGINX, поэтому выполняем следующие две команды:

service nginx reload
service php7.0-fpm reload

Если нет ошибки в запуске служб, заходим на наши сайты и любуемся ими! Для проверки создадим файл 1.php с содержимым:

<?php 
phpinfo();

Закинем его в папку /var/www/site.ru/web.
Теперь при заходе на site.ru/1.php мы должны увидеть экран с текущими настройками PHP, типа такого:
phpinfo.png
Смотрим текущие параметры, подключенные модули PHP и убедждаемся в том, что всё вроде настроено как надо. Тоже самое повторим для сайтов site.org и site.com.

Ещё добавлю один нюанс - иногда организация нашего сайта требует, чтобы все запросы к сайту шли через один шлюз, обычно это index.php. То есть какой бы путь мы ни указали при обращении к сайту, управление будет передано именно index.php. В nginx есть несколько способ организовать подобное и я приведу способ, который используем мы для одного из наших сайтов.
Итак, вот конфиг NGINX для сайта, к которому все запросы (правда, кроме обращения к папке inc, в которой у нас хранятся публичные ресурсы - картинки, JavaScripts и CSS-файлы), идут напрямую index.php, а там мы уже решаем, что делать с данным запросом:

server {
        listen *:80;
        server_name site.com www.site.com;
        root   /var/www/site.com/web;

        index index.html index.php;

        error_log /var/www/site.com/log/error.log;
        access_log /var/www/site.com/log/access.log combined;

        location ~ /\. {
            deny all;
            access_log off;
            log_not_found off;
        }

        location = /favicon.ico {
            log_not_found off;
            access_log off;
        }

        location = /robots.txt {
            allow all;
            log_not_found off;
            access_log off;
        }

        location ~* \.(js|css|png|jpg|jpeg|gif|svg)$ {
            expires max;
            # log_not_found off;
        }

        location ~ \.(php|html)$ {
            try_files /d58f8ccd9bffa83ebec930554209111f.htm @php;
        }

        location @php {
            try_files $uri =404;
            include /etc/nginx/fastcgi_params;
            fastcgi_pass unix:/run/php/php7.0-fpm3.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_intercept_errors on;
        }
        
        location /inc/ {}
        location / {
            rewrite ^ /index.php last;
        }
}

В этом конфиге самые интересные такие блоки:

location /inc/ {}
location / {
rewrite ^ /index.php last;
}

Первый блок приказывает nginx обрабатывать путь к папке inc как есть, а второй блок все запросы перенаправляет файлу index.php.

Добавляем 4-ый сайт: site2.ru - web4

cd /var/www
mkdir -p site2.ru{tmp,web,log}
useradd -m -d /var/www/site2.ru -s $(which bash) -G www-data web4
passwd web4
chown web4:www-data -R /var/www/site2.ru
 
cp /etc/php/7.0/fpm/pool.d/web3.conf /etc/php/7.0/fpm/pool.d/web4.conf
vim /etc/php/7.0/fpm/pool.d/web4.conf
cp /etc/nginx/sites-available/site.com.vhost /etc/nginx/sites-available/site2.ru.vhost
vim /etc/nginx/sites-available/site2.ru.vhost
ln -s /etc/nginx/sites-available/site2.ru.vhost /etc/nginx/sites-enabled/web4
service nginx reload
service php7.0-fpm reload

Настройка FTP сервера

Прежде чем приступить к настройкам почты, настроим FTP сервер, чтобы можно было заходить по FTP(FTPS) в папку сайта и обновлять его. Инсталлируем pure-ftpd:

# apt install pure-ftpd
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
pure-ftpd-common
The following NEW packages will be installed:
pure-ftpd pure-ftpd-common
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 263 kB of archives.
After this operation, 796 kB of additional disk space will be used.
Do you want to continue? [Y/n] y

Настройка Pure-ftpd осуществляется оригинально - надо в папке /etc/pure-ftpd/conf создать файл с именем параметра и вписать требуемое значение в его содержимое. Странно, но ладно. Итак, давайте создадим исполняемый скрипт, который будет задавать нужные нам настройки и потом запустим его:

vim /root/pureftpd-conf.sh
#!/bin/sh
echo 'yes' > ChrootEveryone 
echo '50' > MaxClientsNumber 
echo '10' > MaxClientsPerIP 
echo 'no' > VerboseLog 
echo 'yes' > DisplayDotFiles 
echo 'no' > ProhibitDotFilesWrite 
echo 'yes' > NoChmod 
 echo 'yes' > NoAnonymous 
echo 'yes' > DontResolve 
echo '15' > MaxIdleTime
# 1 - simple or TLS, 2 - TLS only 
echo '2' > TLS
# allow unux users FTPing
echo 'yes' > UnixAuthentication 
echo '1000' > MinUID

Кратко описание настроек: мы делаем chroot для всех, чтобы не лазали по всему нашему серверу, отображаем файлы начинающиеся с точки (в Юникс это типа скрытые файлы) и разрешаем их читать/писать, запрещаем анонимный вход, задаём 15 минут макс. возможного простоя, также обязуем всех клиентов использовать TLS (шифрование) - строка echo '2' > TLS. Конечно, рекомендуется всегда где возможно использовать шифрование, чтобы MIM (men in the middle) не могли перехватывать наши файлы. То есть перехватывать они смогут по-любому, но расшифровать - вряд ли. Недостаток шифрования - более медленная скорость передачи файлов, т.к. тратится время на шифровку/дешифровку. Чтобы полностью отключить шифрование, надо в TLS вписать 0, чтобы разрешить обычные и шифрованный трафик - сюда вписать единичку (1).
Также важен последний параметр echo 'yes' > UnixAuthentication. Помните юзеров, которые мы создавали в связке PHP - NGINX (web1, web2 web3 и т.д.) Теперь мы можем использовать их также в качестве FTP-юзеров. Используем теже пароли, что мы задавали при их создании.

Для того, чтобы использовать TLS, создадим самоподписной сертификат:

# openssl req -x509 -nodes -days 7300 -newkey rsa:2048 -keyout /etc/ssl/private/pure-ftpd.pem -out /etc/ssl/private/pure-ftpd.pem

После всех манипуляций перезапустим наш демон:

# service pure-ftpd restart

PureFTPD пишет логи в syslog. Смотреть:

# tail -f /var/log/syslog

Всё, теперь мы можем соеднияться по FTP(S) (S - secure), указывая пользователей web1,web2, web3, при этом они по умолчанию будут попадать в свои домашние папки, которые являются папками их сайтов.

Настройка почты - Postfix + Dovecot

Итак, у нас есть работающию сайты и FTP доступ к ним, чтобы заливать/обновлять/удалять контент на этих сайтах. Также мы можем работать с базами данных MySQL/SQlite.

Для полноценной работы нам осталось настроить почту, чтобы отсылать/получать письма на своих сайтах или в своей системе. Система почты в общем случае состоит из двух компонентов MTA - mail transer agent, агент передачи почты и MDA - mail delivery agent, агент доставки почты. В качестве золотой пары мы будем использовать Postfix + Dovecot, как наиболее популярные на сегодня, и не зря, по-моему скромному мнению. Итак, инсталлируем пакеты, настраиваем конфиги и создаём почтовые домены и ящики. Поехали!

Шаг 1: Инсталлируем пакеты и устанавливаем сертификат

# apt install postfix postfix-mysql dovecot-core dovecot-imapd dovecot-lmtpd dovecot-mysql dovecot-pop3d
В диалоговом окне указываем : Internet Site, site.ru
Создаём ключ/сертификат dovecot.key и dovecot.pem:
# openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/ssl/private/dovecot.key -out /etc/ssl/certs/dovecot.pem
Мои ответы на вопросы в порядке их возникновения: RU Volgograd Volgograd Justbeo CEO beotiger mymail@gmail.com

Проверяем доступность наших доменов для почты:
# dig MX site.ru +short @ns1.he.net
10 mail.site.ru.
# host mail.site.ru ns1.he.net

Using domain server:
Name: ns1.he.net
Address: 216.218.130.2#53
Aliases:

mail.site.ru has address 131.21.128.229

Шаг 2: Создаём базу данных MySQL, виртуальные домены, пользователей и альясы

Создадим особую БД для хранения наших виртуальных доменов, пользователей и альясов. Назовём её к примеру vmail. В этой базе создадим виртуальные домены под все наши 3 сайта, а также двух пользователя для двух сайтов:

# mysqladmin -p create vmail
mysql > GRANT SELECT ON vmail.* TO 'vmail'@'127.0.0.1' IDENTIFIED BY 'password';
mysql > FLUSH PRIVILEGES;
mysql> USE vmail;
mysql> CREATE TABLE `domains` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

mysql> CREATE TABLE `users` (
`id` INT NOT NULL AUTO_INCREMENT,
`domain_id` INT NOT NULL,
`password` VARCHAR(106) NOT NULL,
`email` VARCHAR(120) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
FOREIGN KEY (domain_id) REFERENCES domains(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

mysql> CREATE TABLE `aliases` (
`id` INT NOT NULL AUTO_INCREMENT,
`domain_id` INT NOT NULL,
`source` varchar(100) NOT NULL,
`destination` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (domain_id) REFERENCES domains(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Наши виртуальные домены. id по умолчанию начинается с 1:
mysql> INSERT INTO `domains` (`name`)
VALUES ('site.ru'), ('site.org'), ('site.com');

mysql> INSERT INTO `users` (`domain_id`, `password` , `email`)
VALUES
('1', ENCRYPT('pass1', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'user1@site.ru'),
('2', ENCRYPT('pass2', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'user2@site.org');

-- добавляем ещё одного пользователя для site.com, не забываем про правильный domain_id:
mysql> INSERT INTO `users` (`domain_id`, `password` , `email`)
VALUES ('3', ENCRYPT('pass3', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'user3@site.com');

-- Note: Warning | 1287 | 'ENCRYPT' is deprecated and will be removed in a future release. Please use AES_ENCRYPT instead

-- добавляем альяс info@site.ru, который будет ссылаться на user1@site.ru, то есть письмо на info@site.ru уйдёт пользователю user1@site.ru. Важно - следует свериться с ид домена из таблицы domains, чтобы поле domain_id ему соответствовало:
mysql> INSERT INTO `aliases` (`domain_id`, `source`, `destination`)
VALUES ('1', 'info@site.ru', 'user1@site.ru');

Аналогично добавляем другие нужные альясы. Чтобы добавить глобальный альяс, который будет пересылать письма, уходящие на любой неопределенный адрес выбранного домена определенному пользователю данного домена:
mysql> INSERT INTO `aliases` (`domain_id`, `source`, `destination`)
VALUES ('1', '@site.ru', 'user1@site.ru');

-- завершаем сеанс работы с MySQL:
QUIT;

Шаг 3: Конфигурируем Postfix

Основные настройки Postfix находятся в двух файлах - main.cf и master.cf. В master.cf можно переопределять некоторые настройки для определённых служб (флаг -o - override, переопределить). Начнём с main.cf. Кратко. что мы тут делаем: используем шифрованние TLS, виртуальные домены и пользователей ч/з MySQL базу, Dovecot. переопределяем только указанные ниже настройки, остальные оставляем по умолчанию, как они были в main.cf изначально:

# cp /etc/postfix/main.cf /etc/postfix/main.cf.orig
# vim /etc/postfix/main.cf
# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/dovecot.pem
smtpd_tls_key_file=/etc/ssl/private/dovecot.key
smtpd_use_tls=yes
smtpd_tls_auth_only = yes

smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions = permit_sasl_authenticated,permit_mynetworks,reject_unauth_destination

# mydestination = $myhostname, site.com, localhost.com, , localhost
mydestination = localhost, localhost.localdomain
myhostname = site.com
## Tells Postfix to use Dovecot's LMTP instead of its own LDA to save emails to the local mailboxes.
virtual_transport = lmtp:unix:private/dovecot-lmtp
## Tells Postfix you're using MySQL to store virtual domains, and gives the paths to the database connections.
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf

Создаём нужные файлы:

# vim /etc/postfix/mysql-virtual-mailbox-domains.cf
user = vmail
password = gR29eZ34
hosts = 127.0.0.1
dbname = vmail
query = SELECT 1 FROM domains WHERE name='%s'

# vim /etc/postfix/mysql-virtual-mailbox-maps.cf
user = vmail
password = gR29eZ34
hosts = 127.0.0.1
dbname = vmail
query = SELECT 1 FROM users WHERE email='%s'

# vim /etc/postfix/mysql-virtual-alias-maps.cf
user = vmail
password = gR29eZ34
hosts = 127.0.0.1
dbname = vmail
query = SELECT destination FROM aliases WHERE source='%s'

Проверка:

service postfix restart
postmap -q site.ru mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
postmap -q user2@site.org mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
postmap -q info@site.ru mysql:/etc/postfix/mysql-virtual-alias-maps.cf

Первые две проверки должны вернуть 1, третья - email для альяса: user1@site.ru

vim /etc/postfix/master.cf


submission inet n - - - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject

Проверим все установки Postfix и сделаем рестарт его (релоада недостаточно что ли?):

postconf -n
service postfix restart

Шаг 4: Конфижим Dovecot

Создаём копии на всякий случай:

cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.orig
cp /etc/dovecot/conf.d/10-mail.conf /etc/dovecot/conf.d/10-mail.conf.orig
cp /etc/dovecot/conf.d/10-auth.conf /etc/dovecot/conf.d/10-auth.conf.orig
cp /etc/dovecot/dovecot-sql.conf.ext /etc/dovecot/dovecot-sql.conf.ext.orig
cp /etc/dovecot/conf.d/10-master.conf /etc/dovecot/conf.d/10-master.conf.orig
cp /etc/dovecot/conf.d/10-ssl.conf /etc/dovecot/conf.d/10-ssl.conf.orig
 
vim /etc/dovecot/dovecot.conf


...
!include_try /usr/share/dovecot/protocols.d
protocols = imap lmtp pop3

vim /etc/dovecot/conf.d/10-mail.conf


mail_location = maildir:/var/mail/vhosts/%d/%n
mail_privileged_group = mail

Создание юзера, папок и проверка доступа
Введем команду:

ls -ld /var/mail

Убедимся, что параметры доступа таковы:

drwxrwsr-x 3 root vmail 4096 Jan 24 21:23 /var/mail

Создаём папки для каждого домена из MySQL таблицы domains

mkdir -p /var/mail/vhosts
cd /var/mail/vhosts
mkdir site.com site.org site.ru

Создаем юзера и группу vmail с id = 5000

groupadd -g 5000 vmail 
useradd -g vmail -u 5000 vmail -d /var/mail

И меняем на него владение папки /var/mail:

chown -R vmail:vmail /var/mail

Теперь правим файл /etc/dovecot/conf.d/10-auth.conf

vim /etc/dovecot/conf.d/10-auth.conf


disable_plaintext_auth = yes
auth_mechanisms = plain login
#!include auth-system.conf.ext
!include auth-sql.conf.ext

Т.е. поменяли авторизацию с системной на MySQL.

vim /etc/dovecot/conf.d/auth-sql.conf.ext


passdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb {
driver = static
args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n
}

vim /etc/dovecot/dovecot-sql.conf.ext


driver = mysql
connect = host=127.0.0.1 dbname=vmail user=vmail password=gR29eZ34
default_pass_scheme = SHA512-CRYPT
password_query = SELECT email as user, password FROM users WHERE email='%u';

chown -R vmail:dovecot /etc/dovecot
chmod -R o-rwx /etc/dovecot
vim /etc/dovecot/conf.d/10-master.conf


##Uncomment inet_listener_imap and modify to port 0
service imap-login {
inet_listener imap {
port = 0
}

#Create LMTP socket and this configurations
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
#inet_listener lmtp {
# Avoid making LMTP visible for the entire internet
#address =
#port =
#}
}

# Modify unix_listener parameter to service_auth like this:

service auth {

unix_listener /var/spool/postfix/private/auth {
mode = 0666
user = postfix
group = postfix
}

unix_listener auth-userdb {
mode = 0600
user = vmail
#group =
}

#unix_listener /var/spool/postfix/private/auth {
# mode = 0666
#}

user = dovecot
}

service auth-worker {
# Auth worker process is run as root by default, so that it can access
# /etc/shadow. If this isn't necessary, the user should be changed to
# $default_internal_user.
user = vmail
}

vim /etc/dovecot/conf.d/10-ssl.conf


ssl = required
ssl_cert =

Посмотреть полную конфигурацию dovecot можно командой:

dovecot -n
service dovecot restart
telnet site.com 993 # проверка открытого порта 993 (IMAP)
telnet site.com 995 # проверка открытого порта 995 (POP3)
telnet site.com 587 # проверка открытого порта 587 (SMTP)

Поздравляю! Мы успешно настроили наш почтовый сервер и теперь можно приступать к тестам!


- Username: user2@site.org
- Password: pass2
- IMAP: site.org:993
- SMTP: site.org:587

Примечание: используем порты 993 для secure IMAP, 587 или 25 для SMTP и 995 для POP3?
Настройки почтовика:
Send: "SMTP Auth automatic" "Use SSL/TLS" "Use STARTTLS command to start encrypted session" "SMTP port: 587"

Шаг 5: Добавляем и конфигурирем SpamAssassin

Инсталлируем SpamAssassin


# apt install spamassassin spamc -- a spamc зачем?
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
binutils cpp cpp-6 dirmngr gcc gcc-6 gnupg gnupg-agent gnupg-l10n libasan3 libatomic1
libc-dev-bin libc6-dev libcc1-0 libcilkrts5 libdigest-hmac-perl libgcc-6-dev
libio-socket-inet6-perl libisl15 libitm1 liblsan0 libmail-spf-perl libmpc3 libmpx2
libnet-dns-perl libnet-ip-perl libnetaddr-ip-perl libquadmath0 libsocket6-perl
libsys-hostname-long-perl libtsan0 libubsan0 linux-libc-dev make manpages manpages-dev
pinentry-curses re2c sa-compile
Suggested packages:
binutils-doc cpp-doc gcc-6-locales tor gcc-multilib autoconf automake libtool flex bison gdb
gcc-doc gcc-6-multilib gcc-6-doc libgcc1-dbg libgomp1-dbg libitm1-dbg libatomic1-dbg
libasan3-dbg liblsan0-dbg libtsan0-dbg libubsan0-dbg libcilkrts5-dbg libmpx2-dbg
libquadmath0-dbg parcimonie xloadimage glibc-doc make-doc pinentry-doc razor
libio-socket-ssl-perl libdbi-perl pyzor libmail-dkim-perl libencode-detect-perl
The following NEW packages will be installed:
binutils cpp cpp-6 dirmngr gcc gcc-6 gnupg gnupg-agent gnupg-l10n libasan3 libatomic1
libc-dev-bin libc6-dev libcc1-0 libcilkrts5 libdigest-hmac-perl libgcc-6-dev
libio-socket-inet6-perl libisl15 libitm1 liblsan0 libmail-spf-perl libmpc3 libmpx2
libnet-dns-perl libnet-ip-perl libnetaddr-ip-perl libquadmath0 libsocket6-perl
libsys-hostname-long-perl libtsan0 libubsan0 linux-libc-dev make manpages manpages-dev
pinentry-curses re2c sa-compile spamassassin spamc
0 upgraded, 41 newly installed, 0 to remove and 0 not upgraded.
Need to get 30.0 MB of archives.
After this operation, 119 MB of additional disk space will be used.
Do you want to continue? [Y/n] yes?

Устанавливаем права доступа

Добавляем группу spamd:

# groupadd spamd

потом пользователя spamd с домашней директорией /var/log/spamassassin:

# useradd -g spamd -s /bin/false -d /var/log/spamassassin spamd

и затем создаём папку /var/log/spamassassin:

# mkdir /var/log/spamassassin

Меняем права доступа к этой папке на spamd:

# chown spamd:spamd /var/log/spamassassin

Займемся непосредственно конфигурацией


# vim /etc/default/spamassassin

Меняем параметр ENABLED для включения самого демона SpamAssassin.

ENABLED=1

Также изменим домашнюю папку и опции:

OPTIONS="--create-prefs --max-children 3 --username spamd -H /var/log/spamassassin/ -s /var/log/spamassassin/spamd.log"

И включаем крон для автоматического апдейта правил SpamAssassin:

CRON=1

Далее открываем файл /etc/spamassassin/local.cf и устанавливаем нужные нам правила анти-спама:

# vim /etc/spamassassin/local.cf

SpamAssassin ставит баллы каждому письму, и если этот балл превысит определенное значение, в нашем примере 5.0, тогда это письмо будет считаться спамом. Можно использовать такие параметры для анти-спам правил:

rewrite_header Subject *** SPAM _SCORE_ ***
report_safe 0
required_score 5.0
use_bayes 1
use_bayes_rules 1
bayes_auto_learn 1
skip_rbl_checks 0
use_razor2 0
use_dcc 0
use_pyzor 0

Теперь меняем один из конфигов Postfix /etc/postfix/master.cf для указания того, что каждое поступающее письмо должно проходить проверку нашим SpamAssassin.

# vim /etc/postfix/master.cf

Находим следующую строку и добавляем фильтр для spamassassin:


smtp inet n - - - - smtpd
-o content_filter=spamassassin

В конце надо будет добавить следующие параметры:

spamassassin unix - n n - - pipe
user=spamd argv=/usr/bin/spamc -f -e
/usr/sbin/sendmail -oi -f ${sender} ${recipient}

Теперь нужно перезапустить наши службы, у которых мы меняли конфиги:

# service spamassassin restart
# service postfix restart

Всё, мои поздравления! Мы успешно сконфижили Postfix с поддержкой SpamAssassin!

Ага, а тесты?!

Тест для SpamAssassin: создайте и пошлите себе письмо со стороннего сервера со следующей темой:

XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X

И ещё можно выполнить следующую команду:

# spamassassin -D < /usr/share/doc/spamassassin/examples/sample-spam.txt

FAIL2BAN

Эта простая, но мощная штука позволяет банить ботов/злоумышленников по ip-адресам на определённые сроки.
Устанавливается и настраивается буквально за пару минут. Правила для большинства служб в ней уже прописаны по умолчанию, а если нам надо добавить что-то своё, это делается на основе регулярок.

Правила прописываются в файле jail.conf, но он может измениться при очередном апгрейде fail2ban, поэтому рекомендуется вносить правила в файл jail.local, который имеет приоритет перед jail.conf.

Итак, приступим, установим пакет и пропишем правила для наших служб:

apt install fail2ban
vim /etc/fail2ban/jail.local
[DEFAULT]
bantime = 600
findtime = 600
maxretry = 3

destemail = admin@site.ru
sender = fail2ban@site.ru
sendername = Fail2Ban
mta = sendmail

action = %(action_mw)s

[sshd]
enabled  = true
port    = 11974
bantime = 3600
logpath  = /var/log/auth.log

[postfix]
enabled  = true
logpath  = /var/log/mail.log
bantime  = 7200

[dovecot]
enabled  = true
logpath  = /var/log/mail.log
findtime = 300
bantime  = 1800

[postfix-sasl]
enabled  = true
logpath  = /var/log/mail.log
findtime = 300
maxretry = 10
bantime  = 1800

FAIL2BAN использует линунксовый файервол для фильтрации и бана.
Посмотрим, какие правила у нас есть перд стартом службы, и какие добавились после её запуска
(замечу, что файревол перед этим мы не настраивали):

service fail2ban stop
iptables -S


-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT

service fail2ban start
iptables -S


-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N f2b-dovecot
-N f2b-postfix
-N f2b-postfix-sasl
-N f2b-sshd
-A INPUT -p tcp -m multiport --dports 110,995,143,993,587,465,4190 -j f2b-dovecot
-A INPUT -p tcp -m multiport --dports 25,465,587,220,993,110,995 -j f2b-postfix-sasl
-A INPUT -p tcp -m multiport --dports 25,465,587 -j f2b-postfix
-A INPUT -p tcp -m multiport --dports 11974 -j f2b-sshd
-A f2b-dovecot -j RETURN
-A f2b-postfix -j RETURN
-A f2b-postfix-sasl -j RETURN
-A f2b-sshd -j RETURN

5 минут спустя получаем 2 адреса в бане:

iptables -S


...
-A f2b-postfix-sasl -s 79.129.39.26/32 -j DROP
-A f2b-postfix-sasl -s 181.214.206.133/32 -j DROP
...

Проверка статуса службы:

systemctl status fail2ban.service


● fail2ban.service - Fail2Ban Service
Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2018-05-06 14:29:15 MSK; 17h ago
Docs: man:fail2ban(1)
Main PID: 1417 (fail2ban-server)
Tasks: 9
Memory: 19.7M
CPU: 35.827s
CGroup: /system.slice/fail2ban.service
└─1417 /usr/bin/python3 /usr/bin/fail2ban-server -s /var/run/fail2ban/fail2ban.sock -p /var/run/fai

Вот и всё, теперь о Fail2Ban, равно как и о ботах, ломящихся на наш сервер, можно забыть. Но расслабляться всё равно не стоит.

Финал

Вот в принципе и всё, конец поста, кто прочёл всё это сначала до конца, без пролистывания, и ещё что-нибудь понял и усвоил без несварения желудка, тому респект и уважуха, всем остальным - чаю, пока! 0_0 ^_^

Делаем дамп БД и отсылаем себе на почту

Введение

Здравствуйте.

Наша задача – периодически делать дамп указанной базы данных (БД) и отсылать нам на почту, чтобы в случае чего можно было восстановиться в любой момент времени.

Для этого достаточно штатных средств Linux‘а.

DB.SH

Итак, составляем простой шелл скрипт – текстовый файл, назовём его db.sh, и делаем его исполняемым:

$ vim /var/adm/cron/db.sh
$ chmod +x /var/adm/cron/db.sh

Учтём, что в папке /var/adm/cron находятся крон-задачи, т.е. периодически выполняемые на нашем сервере, этот каталог не доступен из Интернета.

Вот полное содержимое db.sh:

#!/bin/sh
cd /var/adm/cron/
echo "**" `date +'%Y-%m-%d %H:%I:%S'` "I am db.sh:" `id` >> log.txt
mysqldump -h localhost -u dbuser -pmypassword mydbase > db_dump.sql
bzip2 -f db_dump.sql
date +'%Y-%m-%d %H:%I:%S' | mutt -s 'mydbase backup' -a db_dump.sql.bz2 -- mymail@yandex.ru

Что мы тут делаем:
1. Переходим в каталог, где находится наш скрипт: /var/adm/cron
2. В лог (файл log.txt) выведем текстовое сообщение с текущей датой/времени в формате YYYY-MM-DD HH:mm:ss (год-месяц-число час-минуты-секунды), произвольным сообщением (I’m db.sh) и ид юзера, под которым запущен скрипт. Делать это конечно же не обязательно.
3. Делаем бэкап базы mydbase из-под пользователя dbuser с паролем mypassword (этот пользователь конечно же должен иметь доступ к указанной БД) и сохраняем его в файле db_dump.sql.
4. Сжимаем полученный бэкап архиватором BZIP2 (он сжимает несколько лучше, чем штатный GZIP). Флаг -f (force, форсировать) говорит о том, чтобы перезаписывать старый архив в случае его наличия.
5. Отправляем сообщение на адрес mymail@yandex.ru в виде текущей даты/времени со вложением только что заархивированного дампа базы данных. Замечу, что сам архивированный дамп БД мы оставляем в текущем каталоге, на всякий случай.

MUTT

Самое интересное – 5-ый шаг, мы используем консольный почтовик mutt, хотя это довольно популярная и древняя утилита, в базовые дистрибутивы она обычно по-умолчанию не входит, и её нужно установить командой своего менеджера пакетов, например, для Debian/Ubuntu:

# apt-get install mutt

Также обратите внимание на версию mutt‘а, мы используем версию 1.5.21:

# mutt -v
Mutt 1.5.21 (2010-09-15)
...

Дело в том, что для других версий команда отправки письма с сообщением может отличаться, например для Mutt 1.4.xx версии я использовал такую команду:

date | /usr/local/mutt-1.4.2.3/mutt -s 'mydbase backup' -a db_dump.sql.bz2 mymail@yandex.ru

Обратите внимание на разницу передачи пайпа от команды date к mutt‘у. Как говорится, найдите 10 отличий.

Если вы не являетесь админом на сервере, как вариант собрать mutt из исходников, и указывать абсолютный путь к нему. Я так делал на SpaceWeb‘е. Либо загуглить статически линкованный mutt. Я сейчас в первой 20-ке не смог найти статического mutt‘а по запросу `mutt static build download`. В этом случае можно собрать статический mutt у себя на локальном компьютере, инструкции как это сделать найти можно, и перенести его на сервер.

Также mutt можно заменить на утилиту mail, входящую в пакет mailx (или один из его производных). Если на сервере доступна команда mail, отослать наш дамп БД как вложение можно командой:

$ mail -s "mydbase backup" -a "db_dump.sql.bz2" "mymail@yandex.ru" <<< $(date +"%Y-%m-%d %H:%I:%S")

Параметры здесь практические такие же, что и у mutt: -s – тема, -a – аттачмент.

CRON

Теперь добавим вызов скрипта в cron. Мне достаточно делать дамп БД раз в сутки, настрою вызов скрипта каждый день, в 5:13 утра:

$ crontab -e
13 	5 	* 	* 	* 	/var/adm/cron/db.sh

Либо как вариант закинуть db.sh в папку /etc/cron.daily, если есть к ней доступ. Рабочей папкой для скрипта всё равно останется /var/adm/cron, всю работу он будет делать там.

SPLIT

Но в один прекрасный день я не получил на почту утром дамп нашей БД. Поискав логах, я нашёл примерно такую ошибку:

postdrop: warning: uid=0: File too large
sendmail: fatal: root(0): message file too big
Сообщение отправить не удалось, процесс-потомок вернул 75 (Deferred.).
Сообщение отправить не удалось.

Ага, этого рано-поздно следовало ожидать. Дамп нашей базы оказался слишком велик для передачи по электронной почте. Тут у нас есть пара вариантов (как хорошо, что жизнь компьютерная почти всегда предоставляет нам несколько решений одной и той же проблемы, что касается программирования или системного администрирования, вот бы в реальной жизни всё было бы так же).
1. Увеличить макс.размер отправляемых писем. Если Вы админ, это можно легко сделать. mutt, впрочем как и mail(x), использует установленный в системе mail-transport-agent (MTA), из коих наиболее распространёнными на сегодня пожалуй являются Postfix и Exim4. Пример с Postfix‘ом как увеличить максимальный размер отсылаемых писем:

# postconf | grep message_size_limit
message_size_limit = 10240000
# postconf -e "message_size_limit = 51200000"
# postconf | grep message_size_limit
message_size_limit = 51200000

Сперва мы узнали макс.размер письма, который оказался равен 10 мегабайт, затем увеличили его до 50 мегабайт. Да, у Postfix‘а по-умолчанию размер письма (message) включая возможные аттачи максимум 10 мегабайт. Размер последнего дампа БД, который удалось отправить, был равен 8.6 мегабайт, файлы большего размера уже не отправлялись, что довольно странно, так как до 10 мегабайт было ещё не так скоро. Хотя на самом деле аттачи отправляются в uuencoded (или base64-encoded) формате, и если мы закодируем так наш последний полученный по почте дамп, то получим размер 11,970,592 байта в chunk_split(base64_encode($attach)) или размер 12,052,444 байт при использовании convert_uudecode($attach) – были использованы стандартные PHP функции. В обоих случаях размер превышает заданный по умолчанию в Postfix‘е 10,240,000 байт.

ОК, если мы увеличим макс.разрешенный размер письма до 50 мегабайт, то мы получим какое-то время, возможно в несколько лет (если наша БД не очень быстро пополняется), прежде чем мы превысим макс.допустимый объём.

Да, тут несколько возможных проблем – рано или поздно аттач (в смысле письмо с ним) опять превысит макс.допустимый размер и перестанет отправляться, второе – принимающий сервер может со своей стороны ограничивать размер принимаемых писем. Третье – вы можете не быть админом на сервере и повысить максимальный размер письма. В скобках замечу, что, указав message_size_limit = 0 вы снимете ограничение на максимальный размер письма.

Во всех этих случаях нас выручит split, старый добрый split. Давайте будем пилить наш аттач например по 5 мегабайт и кусками отправлять нам на почту. Делается это примерно так:

split -b 5M db_dump.sql.bz2 dump5M_
 
for i in dump5M_*
do
date +'%Y-%m-%d %H:%I:%S' | mutt -s 'mydbase backup' -a $i -- mymail@yandex.ru
done
 
# почистим за собой
rm dump5M_*

Таким образом новый готовый скрипт db.sh будет выглядеть так:

#!/bin/sh
cd /var/adm/cron/
echo "**" `date +'%Y-%m-%d %H:%I:%S'` "I am db.sh:" `id` >> log.txt
mysqldump -h localhost -u dbuser -pmypassword mydbase > db_dump.sql
bzip2 -f db_dump.sql
split -b 5M db_dump.sql.bz2 dump5M_
 
for i in dump5M_*
do
date +'%Y-%m-%d %H:%I:%S' | mutt -s 'mydbase backup' -a $i -- mymail@yandex.ru
done
 
# почистим за собой
rm dump5M_*

При задании в split имени dump5M_ мы получаем файлы вида dump5M_aa, dump5M_ab, dump5M_ac и т.п. Чтобы склеить при случае полученные куски, можно обойтись штатными средствами системы:

В Windows (кавычки в именах файлов обязательны):

C:\Users\Andrey\Desktop> copy /b "dump5M_aa" + "dump5M_ab" db.sql.bz2

В Linux:

$ cat dump5M_aa dump5M_ab > db.sql.bz2

или:

$ cat dump5M_a* > db.sql.bz2

И в случае применения split’а есть недостаток, если, например, размер дампа 50 мегабайт, то мы будем каждый день отсылать/получать по 10 писем, не знаю, хорошо это или плохо. Как вариант – отсылать дамп БД на резервный сервер, к примеру с помощью команды scp, но это пожалуй уже другая история.

На сим всё, раскланиваюсь, т.к. наша задача выполнена на 100% и мы можем теперь спать спокойно, не боясь краха нашего сервера и утери нашей драгоценной базы данных с кредитной историей наших клиентов.

Спокойной ночи, сладких снов, если уже ночь, чашки кофе и стакана апельсинового сока, если утро, бокала пива с жаренными креветками, если обед, бутылки виски или Шардоне, если вечер.

Инсталлируем и конфижим DKIM с Postfix на Debian/Ubuntu

Перевод с https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-dkim-with-postfix-on-debian-wheezy

Введение

Для многих серверных админов попадние в спам-лист не является такой уж редкой возможностью, тогда как конечно никакой спам они не рассылают и не рассылали. Возможные способы попадния в спам-листы сервера (при условии что Ваш сервер чист, не заражен троянами, рассылающего спам без Вашего ведома) могут быть одними из:

  • Сервер явлется открытым почтовым релеем (open mail relay), позволяющим любому пересылть через него тонны писем
  • IP адрес сервера находится в черном списке (blacklisted)
  • Сервер не имеет Fully Qualified Domain Name (FQDN) и соотв. записи PTR
  • the Sender Policy Framework (SPF) DNS record отсуттствует или неверно сконфижен
  • the DomainKeys Identified Mail (DKIM) отсутствует ил опять же неверно настроен

Это основные требования, проверяемые многими спам-фильтрами (включая SpamAssasin).

Это руководство (tutorial) описывает инсталляцию и конфигурирование OpenDKIM: открытую имплементацию DKIM.

Важно: замените `example.com` на имя своего домена во всех примерах ниже. Команды выполняются от имени суперпользователя (su). При необохдимости используйте sudo, если предпочитаете не быть суперзверем на своём сервере. Также на системах Ubuntu вместо apt-get можно использовать apt с подобным синтаксисом. (Это была вставка от меня, Андрея Царя, простите за вольности).

Postfix и Dovecot должны быть уже установлены и сконфижены как следует (руководства (tutorial)), имя хоста и the FQDN заданы (tutorial, tutorial) и запись SPF на своём месте (tutorial).

О DKIM

DKIM – это интернет-стандарт, который позволяет частному лицу либо организации связать имя домена с email-сообщением.. То есть в какой-то мере это метод, подтверждающий достоверность и легальность отправляемого письма. В своей сути, DKIM основан на асимметричной криптографии. Mail Transfer Agent (MTA) отправителя подписывает каждое исходящее сообщение приватным ключом. Принимающая сторона получает публичный ключ из поля DNS и удостоверяется в том, что тело сообщения и некоторые заголовки не были изменены после подписывания письма.

Инсталлируем OpenDKIM

Перед началом инсталляции рекомендуется полный апгрейд системы:

apt-get update
apt-get upgrade

Инсталлируем OpenDKIM и его зависимости:

apt-get install opendkim opendkim-tools

Конфижим OpenDKIM

Теперь надо создать несколько файлов для конфигурироания OpenDKIM.

Итак, начнём с основного файла конфигурации:

vim /etc/opendkim.conf

Добавьте строки в конец conf-файла (каждый параметр будет объяснен позже). Также вы можете выбрать другой номер порта для опции Socket. Убедитесь, что порт не используется другим приложением. Также замечу, что ключевое слово milter обозначает mail filter, т.е. почтовый фильтр.

AutoRestart             Yes
AutoRestartRate         10/1h
UMask                   002
Syslog                  yes
SyslogSuccess           Yes
LogWhy                  Yes

Canonicalization        relaxed/simple

ExternalIgnoreList      refile:/etc/opendkim/TrustedHosts
InternalHosts           refile:/etc/opendkim/TrustedHosts
KeyTable                refile:/etc/opendkim/KeyTable
SigningTable            refile:/etc/opendkim/SigningTable

Mode                    sv
PidFile                 /var/run/opendkim/opendkim.pid
SignatureAlgorithm      rsa-sha256

UserID                  opendkim:opendkim

Socket                  inet:12301@localhost
  • AutoRestart: перезапуск фильтра при ошибке
  • AutoRestartRate: макс.рестарт рэйт, если будет превышен, фильтр остановится; 10/1h – 10 рестартов в час позволено
  • UMask: полный доступ группе с ID = UserID и позволяет другим читать и запускать файлы, в данном случае позволна модификация файла Pid.
  • Syslog, SyslogSuccess, *LogWhy: включают детальный логинг для syslog
  • Canonicalization: определяют методы канонизации, используемые при подписи писем simple метод практически не позволяет модификации, тогда как relaxed допускает минимальные изменения, такие как замена whitespace; relaxed/simple – заголовок письма будет обрабатываться алгоритмом relaxed, а тело письма – simple алгоритмом
  • ExternalIgnoreList: определяет внешние хосты, которые могут слать почту ч/з сервер как один из подписанный оменов без проверки
  • InternalHosts: определяет список внутренних хостов, чью почту не проверяем, но подписываем
  • KeyTable: карта имен ключей для ключей подписи
  • SigningTable: списки применяемых к письмам подписей основанных на адресе, найденном в поле From: заголовка
  • Mode: описывает режимы; в нашем случае milter действует как подписчик (signer) (s) и контроллер (verifier) (v)
  • PidFile: путь к Pid-файлу который содержит ид процесса
  • SignatureAlgorithm: выбирает алгоритм подписывания писем
  • UserID: opendkim процесс выполнятеся от имени данного юзера и группы
  • Socket: milter будет слушать на сокете, определённом здесь, Posfix будет слать письма на проверку и подпись к opendkim ч/з этот сокет; 12301@localhost определяет TCP сокет, слушающий на localhost, порт 12301. Если порт 12301 занят, можно использовать любой другой свободный порт

Эта простая конфигурация позволяет подписывать сообщения для одного или более доменов, для ознакомления с другими опциями посмотрите здесь.

Соединяем milter с Postfix:

vim /etc/default/opendkim

Добавляем следующую строку, номер порта используем из опции Socket выше:

SOCKET="inet:12301@localhost"

Просим Postfix использовать наш milter:

vim /etc/postfix/main.cf

Убедимся что следующие две строчки присутствуют в файле и не закомментированы:

milter_protocol = 2
milter_default_action = accept

Вполне возможно что фильтры (SpamAssasin, Clamav etc.) уже используются Postfix; если да, до добаляем наш milter через запятую, вот так (не забываем про номер порта как в opendkim.conf):

smtpd_milters = unix:/spamass/spamass.sock, inet:localhost:12301
non_smtpd_milters = unix:/spamass/spamass.sock, inet:localhost:12301

Если же данных параметров нет, просто добавляем следующие две строчки в файл:

smtpd_milters = inet:localhost:12301
non_smtpd_milters = inet:localhost:12301

Создаём структуру каталогов, содержащих доверенные хосты, таблицы ключей и криптования

mkdir -p /etc/opendkim/keys

Определяем доверенные хосты:

vim /etc/opendkim/TrustedHosts

Будем использовать этот файл для определения ExternalIgnoreList и InternalHosts, сообщения с этих хостов, доменов и IP-адресов являются доверенными и будут подписаны.

Т.к. наша основная конфигурация объявила TrustedHosts как файл регулярных выражений (refile), мы можем использовать wildcard’ы, т.е. *.example.com означает, что сообщения с поддоменов example.com войдут также в число доверенных, как и сообщения с самого домена example.com.

Добавьте следующие строки в новый файл. Множество доменов может быть добавлено здесь:

127.0.0.1
localhost
192.168.0.1/24

*.example.com

#*.example.net
#*.example.org

Создаём таблицу ключей:

vim /etc/opendkim/KeyTable

Таблица ключей содержит каждую пару селектор/домен и путь к их приватным ключам. Любая строка из латинских буквa и цифр может быть селектором, в нашем примере мы используем mail.

mail._domainkey.example.com example.com:mail:/etc/opendkim/keys/example.com/mail.private

#mail._domainkey.example.net example.net:mail:/etc/opendkim/keys/example.net/mail.private
#mail._domainkey.example.org example.org:mail:/etc/opendkim/keys/example.org/mail.private

Создём таблицу подписи:

vim /etc/opendkim/SigningTable

Этот файл используется для объявления адресов домен/email и их селекторов.

*@example.com mail._domainkey.example.com

#*@example.net mail._domainkey.example.net
#*@example.org mail._domainkey.example.org

Генерируем public и private ключи

Перейдём в каталог с ключами:

cd /etc/opendkim/keys

Создаём отдельную папку для каждого домена, где будут храниться ключи:

mkdir example.com
cd example.com

Генерируем ключи:

opendkim-genkey -s mail -d example.com

-s определяет селектор, а -d определяет домен, эта команда создаст два файла:mail.private это наш private ключ, а mail.txt содержит public ключ.

Поменяем владельца private ключа на opendkim:

chown opendkim:opendkim mail.private

Добавим public ключ к DNS записям домена

Откроем mail.txt:

vim mail.txt

public ключ определён под параметром p. Пример:

mail._domainkey IN      TXT     ( "v=DKIM1; k=rsa; "
          "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5N3lnvvrYgPCRSoqn+awTpE+iGYcKBPpo8HHbcFfCIIV10Hwo4PhCoGZSaKVHOjDm4yefKXhQjM7iKzEPuBatE7O47hAx1CJpNuIdLxhILSbEmbMxJrJAG0HZVn8z6EAoOHZNaPHmK2h4UUrjOG8zA5BHfzJf7tGwI+K619fFUwIDAQAB" )  ; ----- DKIM key mail for example.com

Скопируйте этот ключ и добавьте запись TXT для своего домена в DNS:

Имя: mail._domainkey.example.com.

Text: "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5N3lnvvrYgPCRSoqn+awTpE+iGYcKBPpo8HHbcFfCIIV10Hwo4PhCoGZSaKVHOjDm4yefKXhQjM7iKzEPuBatE7O47hAx1CJpNuIdLxhILSbEmbMxJrJAG0HZVn8z6EAoOHZNaPHmK2h4UUrjOG8zA5BHfzJf7tGwI+K619fFUwIDAQAB"

Измения в DNS могут занять какое-то время до вступления в силу.

Перезапуск Postfix и OpenDKIM:

service postfix restart
service opendkim restart

Мои поздравления! Мы успешно настроили DKIM для нашего почтового сервера!

Конфигурация может быть протестирована отправкой пустого email’а на check-auth@verifier.port25.com. Если всё работает как должно, мы должны будем получить письмо, где среди прочего должна присутствовать строка DKIM check: pass под заголовком Summary of Results.

==========================================================
Summary of Results
==========================================================
SPF check:          pass
DomainKeys check:   neutral
DKIM check:         pass
Sender-ID check:    pass
SpamAssassin check: ham

Также можно послать письмо на наш адрес в Gmail и посмотреть исходники полученного письма, там должна присутствовать строка dkim=pass под заголовком Authentication-Results.

Authentication-Results: mx.google.com;
       spf=pass (google.com: domain of contact@example.com designates --- as permitted sender) smtp.mail=contact@example.com;
       dkim=pass header.i=@example.com;
Создано: П. Себастьян (P. Sebastian)
Перевод: А. Царь (beotiger)

Retrospec: ещё немного ретро-игр для Linux

Здравствуйте!

И по следам предыдущего поста, посвященного крутым римэкам от BrainGames.

Есть ещё одна контора (и наверное не одна, но та, что мне на глаза попалась) – Retrospec – хорошее название для конторы, занимающейся retro-играми, верно?

У них куча ретро-игр, с улучшенной графикой, только одно плохо –
мало игр для Линукса и сорцы даны лишь для малой части игр.

Мне удалсоьс найти сорцы и скомпилить под Линукс только такие их игры:
Alien8, DeflektorX4, Humphrey, Jumping Jack, Jumping Jack 2 : Worryingly Familiar, Styx, TranzAm.

Не густо, не густо. Особенно жаль такие хиты как Exolon DX, Head over Heels, Jet Set Willy.
Ну, вы понимаете о чём я. Почему Retrospec не предоставили сорцы для таких игр, не ведаю.
Может, им написать? Возможно, они вышлют нам сорцы недостающих игр?

Итак, вытрем сопли и продолжим жить. Перейдем к делу, будем работать с тем, что есть.
Если ребята из BrainGames использовали кросс-платформенную библиотеку SDL (SDL 1.2),
(https://www.libsdl.org/) и это получилось у них совсем неплохо, имхо, даже супер-отлично,
то ребята из RetroSpec используют другую, не менее известную
кросс-платформенную библиотеку Allegro – http://alleg.sourceforge.net/ https://www.allegro.cc/

Честно говоря, я изучал SDL кое-как и даже умудрился перепиисать эмулятор Apple2 – AppleWin
под Линукс, используя эту либу (SDL 1.2), но больше ничего под неё так и не написал путного
(если не считать переделку gdwgraph – https://github.com/beotiger/gdwgraph, но это не то, что хотелось бы).

А про Аллегро я краем уха слышал что-то, пару примеров по-моему даже пробовал, но в итоге пока не пошло.
А жаль, надо бы поизучать эту либу подробнее.

Итак, ставим девелоперскую версию Allegro (для сборки из исходников нам всегда будут нужны девелоперские версии либ,
(обычные версии либ нужны тогда, когда у нас есть готовые бинарники, и мы не собираемся их пересобирать).

$ apt install build-essential liballegro4-dev liballegro4.4-plugin-alsa

build-essential я сюда привел для галочки, если вы не собирали игры из прошлого поста,
и у вас в системе не установлен стандартный GNU-компилятор GCC/G++ и сопуствующие ему утилиты и либы.
Так же, чтобы в Аллегро был звук, надо доустановить пакет liballegro4.4-plugin-alsa. Подробнее тему ищите где-то внизу.

Да, у меня по умолчанию установилась 4-ая версия Allegro, хотя в репозиториях уже есть 5-ая версия.
Под 4-ой все собралось и работает нормально, поэтому 5-ую версию я не испытвал.

Ещё для некоторых игр может потребоваться Adime либа (http://adime.sourceforge.net/) –
создание диалогов для Allegro. Можно попробовать собрать отдельно под себя эту либу,
если не сможете найти её для своего дистро.
И плюс FBlend – старый (здесь всё старое, это же РЕТРО!) движок смешивания рисунков.
Его можно взять здесь: https://sourceforge.net/projects/fblend

Я мучался с этими либами, уже не помню точно как (читайте во второй части поста),
но в итоге всё получилось.
Вы можете скачать архив с либами для x86_64 и i386 версий отсюда: http://beotiger.com/download/retrolibs. Туда входят fmodex, adime, fblend и allegro (на всякий случай, аллегро можно установить под любой дистро, отдельно i386 или x86_64 версии). Теоретически должны работать на любых версиях (точнее, дистрибутивах) Линукса, я использовал их на Linux Mint. Используйте их, если не найдете версии для своей системы.

Да, давайте напомним текущую дату (дату поста), систему и наш компилятор:

$ date ; uname -a ; g++ –version
Вт. июня 9 14:47:56 MSK 2015
Linux justy 3.13.0-51-generic-tuxonice #84~ppa1-Ubuntu SMP Wed Apr 29 19:39:16 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Так же для некоторых игр от Retrospec нам может понадобиться FMOD – http://www.fmod.org/
Ооох, это долгая история, с учётом того что исходники старые (им больше 10 лет наверное),
и за это вермя поменялось несколько версий FMOD.
Версия FMOD Ex (FMOD 4), которая пришла на смену FMOD 3, работает без проблем,
и её so-файлы и заголовки для include можно скачать с оф.сайта в секции Old/Legacy или как оно там называется.

Версии FMOD 3 для 64-битной платформы я вообще не нашёл, и судя по ответу оф.лица, её не было выпущено.
Только одна игра – TranzAm – требует FMOD3, но я благополучно переделал её под FMOD Ex. За пару дней.

Я лично установил libfmodex64.so в /usr/lib, где она всегда видна линковщику, и прилинковываю как -lfmodex64. А .h файлы закинул в /usr/include, без всяких подпапок, чтобы инклудить их напрямую. Хотя тут конечно, лучше выделить под это дело свою папку.

Процесс этот описан более подробно ниже. А сейчас приведем процесс сборки всех доступны игр.

Скачать архивчик с играми с сорцами от RetroSpec можно отюда: http://beotiger.com/download/retrospec
Архив весит около 33 мегабайт. Скачиваем архив, распаковываем его, и запускаем в его корневой папке терминал/консоль.

Итак, поехали:

Часть Первая

1. Alien8

$ cd Alien8/src
$ make
$ cp alien8 ..
$ cd ..
$ ./alien8

Красота! И звук и музыка есть (если Вы доустановили пакет ALSA, по крайней мере в моём случае).

Фирменная заставка от RetroSpec, мы её часто будем видеть в их играх:
 

Alien8 скриншоты/screenshots

al1.jpg

al2.jpg

al3.jpg

al4.jpg

2. DeflektorX4

$ cd DeflektorX4/src
$ make
$ cp deflector ..
$ cd ..
$ ./deflector
 

DeflektorX4 скриншоты/screenshots

def1.jpg

def2.jpg

Красота! Смысл игры – поворачивать линзы так, чтобы уничтожить лучом все шарики, и не попасть под колючки.
Даётся лимит энергии, если она кончается, уровень приходится начинать сначала! Я 1-ый уровень так и не смог пройти.

Линзы поворачиваются левой/правой кнопкой мыши, игра вообще рассчитана не на клаву, а на мышь.

3. Humphrey

$ cd Humphrey/src
$ make
$ cp humphrey ..
$ cd ..
$ ./humphrey

 

Humphrey скриншоты/screenshots

hum1.jpg

hum2.jpg

Музыка – класс! Обожаю! Есть выбор языка игры – Cervantes или Shakespeare. Жаль Pushkin нет. Или Tolstoy.

4. Jumping Jack

$ cd jj/src
$ make
$ cd ..
$ ./jj
 

Jumping Jack скриншоты/screenshots

jj1.jpg

jj2.jpg

Что за игра? Прыгать под пролетом, стараться не падать. Игра тупая и непорстая, я так и не дошёл до верха, всё время что-то мешало.
F10 – быстрый выход. Музыки нет, но звук есть.

5. Jumping Jack 2 : Worryingly Familiar

$ cd jjwf/src
$ make
$ cp jjwf ..
$ cd ..
$ ./jjwf
 

Jumping Jack 2 : Worryingly Familiar скриншоты/screenshots

jjwf1.jpg

jjwf2.jpg

Игра такая же, как и JJ, только другая?

6. Styx

$ cd styx/src
$ make
$ mv styx ..
$ cd ..
$ ./styx
 

Styx скриншоты/screenshots

styx1.jpg

styx2.jpg

styx3.jpg

Где-то я прочитал, что это первая игра одного из членов команды RetroSpec. Или нет?
Но похоже на то. Моя первая игра была не лучше. но и не хуже! А какая, она, наша первая игра?

7. TranzAm

С этой игрой – долгая история. Да, FMOD 3 -> FMOD Ex. Это пол-беды. Но она не работает,
если откомпилена в 64-битном режиме, выдает segmentation fault в самых разных местах,
и графика глючит, шрифты (FancyFonts – прыгающие или танцующие буквы), Blender – наложение текстур,
и спрайты испорчены частично.

Но когда мне удалось таки перекомпилить игру в 32-битном режиме (-m32), все эти косяки и глюки практически исчезли.

Игрушка неплоха, это Transport America – ездеешь по карте Америки, штатам, собираешь кубки.
Вредные машинки тебе стараются мешать. Бензин тоже кончается, но полно заправок.

Музыка – супер!

Итак, сейчас она компилится без проблем в 32-разрядном режиме, но возможно,
надо будет найти 32-разрядные версии некоторых библиотек, я нагло спер их из дистрибутива Ubuntu 32 bit.
Фишка в том, что 32-разрядные либы мы кладем в папку /usr/lib/i386-linux-gnu, где линкер сам их найдет, когда надо.
Инфу подробнее вы сможете найти ниже, в описании первичной сборки проектов RetroSpec.

$ cd TranzAm32/src
$ make
$ cd ..
$ ./TranzAm
 

TranzAm скриншоты/screenshots

tranzam1.jpg

tranzam2.jpg

tranzam3.jpg

Да, осталась пара issues, но они не смертельны. Удачи!

===================================================================================

На этом игры собственно все. Мне ещё удалось собрать несколько сторонних проектов – AXL_Projects, IsoMot, TileExtractor, но теперь думаю, вы сами без труда сможете при необохдимости собрать и потестировать их.

В этом нет ничего сложного!

AXL_Projects

, test2 :
 

axl.jpg

IsoMot

:
 

isomot.jpg

TileExtractor

 

tileex.jpg

===================================================================================

Всё, а ниже процесс грязной (первичной сборки), рывками конечно.

Часть Вторая

Retro games from: http://retrospec.sgn.net
Compiling with allegro and fmod?

Allegro:
liballegro4-dev (version 2:4.4.2-4) will be installed
liballegro4.4 (version 2:4.4.2-4) will be installed
libjpgalleg4.4 (version 2:4.4.2-4) will be installed
libxpm-dev (version 1:3.5.10-1) will be installed

Компилим примерно так:
$ gcc -o `allegro-config –cflags` `allegro-config –libs` 051sc.c

FMod нет в репозитории Mint'а?
See: https://wiki.debian.org/FMOD

ОК, качаем Линукс-версию с http://www.fmod.org/download
fmodstudioapi10602linux

Ой, новая версия несовместимса со старой. Ой-ой-ой… Ёёёёёёёперный театр!

Качаем отсюда: http://www.fmod.org/download-previous-products/
(http://www.fmod.org/download/fmodex/api/Linux/fmodapi44453linux.tar.gz)
Это fmod Ex, а не FMod Studio.

justy@justy ~/src/FMOD/fmodapi44453linux/api/inc $ sudo cp * /usr/include/
ls /usr/include/ | grep fmod

justy@justy ~/src/FMOD/fmodapi44453linux/api/lib $ ls
libfmodex-4.44.53.so libfmodex64.so libfmodexL64-4.44.53.so libfmodexL.so
libfmodex64-4.44.53.so libfmodexL-4.44.53.so libfmodexL64.so libfmodex.so
justy@justy ~/src/FMOD/fmodapi44453linux/api/lib $ sudo cp * /usr/lib/
justy@justy ~/src/FMOD/fmodapi44453linux/api/lib $ ls /usr/lib/ | grep fmod | wc -l
8
justy@justy ~/src/FMOD/fmodapi44453linux/api/lib $ ls | wc -l
8

Компилим Alien8

OK, вроде теперь audio откомпилилось!

justy@justy ~/src/retrospec/alien8_f $ make
c++ -w `allegro-config –cflags` -c -o internet.o internet.c
internet.c:13:22: fatal error: winalleg.h: No such file or directory
#include "winalleg.h"
^
compilation terminated.
make: *** [internet.o] Error 1

> Да, в intenent.c надо вставить свою ОС вместо Windows

justy@justy ~/src/retrospec/alien8_f $ make
g++ Alien8.o audio.o internet.o isomot.o juego.o tcj.o tiempo.o -o alien8 `allegro-config –libs` -lfmodex
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/libfmodex.so when searching for -lfmodex
/usr/bin/ld: skipping incompatible /usr/lib/../lib/libfmodex.so when searching for -lfmodex
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../libfmodex.so when searching for -lfmodex
/usr/bin/ld: skipping incompatible //usr/lib/libfmodex.so when searching for -lfmodex
/usr/bin/ld: cannot find -lfmodex
collect2: error: ld returned 1 exit status
make: *** [alien8] Error 1

> Да, в Makefile надо всатвить -lfmodex64 вместо -lfmodex, так как мы компилим под x64 систему.

justy@justy ~/src/retrospec/alien8_f $ make
g++ Alien8.o audio.o internet.o isomot.o juego.o tcj.o tiempo.o -o alien8 `allegro-config –libs` -lfmodex64
internet.o: In function `inet_connect(char*)':
internet.c:(.text+0x38): undefined reference to `curl_global_init'
internet.c:(.text+0x50): undefined reference to `curl_easy_init'
internet.c:(.text+0x85): undefined reference to `curl_easy_setopt'
internet.c:(.text+0xa2): undefined reference to `curl_easy_setopt'
internet.c:(.text+0xc0): undefined reference to `curl_easy_setopt'
internet.c:(.text+0xcf): undefined reference to `curl_easy_perform'
internet.c:(.text+0xfb): undefined reference to `curl_easy_setopt'
internet.o: In function `inet_close()':
internet.c:(.text+0x13f): undefined reference to `curl_easy_cleanup'
internet.c:(.text+0x144): undefined reference to `curl_global_cleanup'
internet.o: In function `inet_sendscore(char*, char*)':
internet.c:(.text+0x1ca): undefined reference to `curl_easy_setopt'
internet.c:(.text+0x1d9): undefined reference to `curl_easy_perform'
collect2: error: ld returned 1 exit status
make: *** [alien8] Error 1

> Ой, он curl хочет? Сейчас дадим!

=========================================================================================

Compiling Humphrey:
Надо установить dumb вместо fmod'а для аудио!

DUMB is a tracker library with support for IT, XM, S3M and MOD files. It
targets maximum accuracy to the original formats, with low-pass resonant
filters for the IT files, accurate timing and pitching, and three resampling
quality settings (aliasing, linear interpolation and cubic interpolation).

Selecting previously unselected package libdumb1:amd64.
(Reading database … 174699 files and directories currently installed.)
Preparing to unpack …/libdumb1_1%3a0.9.3-6_amd64.deb …
Unpacking libdumb1:amd64 (1:0.9.3-6) …
Selecting previously unselected package libdumb1-dev:amd64.
Preparing to unpack …/libdumb1-dev_1%3a0.9.3-6_amd64.deb …
Unpacking libdumb1-dev:amd64 (1:0.9.3-6) …
Setting up libdumb1:amd64 (1:0.9.3-6) …
Setting up libdumb1-dev:amd64 (1:0.9.3-6) …
Processing triggers for libc-bin (2.19-0ubuntu6.6) …

> Нет, та же ошибка:
justy@justy ~/src/retrospec/Humphrey/src $ make
c++ -w `allegro-config –cflags` -c -o audio.o audio.c
audio.c:11:20: fatal error: aldumb.h: No such file or directory
#include <aldumb.h>
^
compilation terminated.
make: *** [audio.o] Error 1

> Оказывается, есть aldumb.h – версия DUMB для Allegro (al – это от allegro).

Устанавливаем пакет:
Selecting previously unselected package libaldmb1:amd64.
Preparing to unpack …/libaldmb1_1%3a0.9.3-6_amd64.deb …
Unpacking libaldmb1:amd64 (1:0.9.3-6) …

Нам нужна dev версия:
Preparing to unpack …/libaldmb1-dev_1%3a0.9.3-6_amd64.deb …
Unpacking libaldmb1-dev:amd64 (1:0.9.3-6) …
Setting up libaldmb1-dev:amd64 (1:0.9.3-6) …

> Да, прошло, но теперь:
c++ -w `allegro-config –cflags` -c -o humphrey.o humphrey.c
humphrey.c: In function ‘int main()’:
humphrey.c:126:12: error: ‘ini_texto’ was not declared in this scope
ini_texto();
^
humphrey.c:145:12: error: ‘fin_texto’ was not declared in this scope
fin_texto();
^
humphrey.c: In function ‘void elegir_idioma()’:
humphrey.c:172:65: error: ‘escribir_texto’ was not declared in this scope
escribir_texto(buffer,"elige tu idioma",96,150,f<31?256-f*8:0);

humphrey.c должен быть откомпилен последним?
Нет, просто include "text.h" потерялось для двух файлов.

Пришлось тажке добавить флаг компилятор -fpermissive, чтобы перестал ругаться на conversion error,
а также для линковщика присобачить две dumb либы: -ldumb -laldmb

Игра работает, но звука нет. Чёртов dumb не хочет звучать что-то…

А вот FMOD в предыдущей проге (alien8) вроде звучал нормально!

========================================================================================
15 May 2015AD: DeflektorX4 с помощью Makefile от Alien8 скомпилился практически сразу,
только в internet.c пришлось опять же закомментить строку WIN, и откомментить LIN.
========================================================================================

16 May 20156AD: Пробуем TranzAm

Очуметь, тут папки code и external.
Скопировал Makefile из Alien8, поменял TARGET, c => cpp, плюс ещё каталог external добавил

OBJECTS = $(SOURCES:.cpp=.o) – заметь, cpp вместо c раньше мы только с C работали.

Пошло вроде ОК, но:
c++ -w -fpermissive `allegro-config –cflags` -c external/lib_fmod.cpp -o external/lib_fmod.o
external/lib_fmod.cpp:1:29: fatal error: ..\game_transam.h: No such file or directory
#include "..\game_transam.h"

Так как мы в эту диру не переходим, всё ищется в текущей дире?
Попробуем убрать .. в этом include (файл external/lib_fmod.cpp).
А, нет, тут надо обратный слэш виндовый заменить на прямой. Тогда пошло вроде, но эти слеши ещё есть:
justy@justy ~/src/retrospec/TranzAm/src/code/code $ make
c++ -w -fpermissive `allegro-config –cflags` -c external/lib_fmod.cpp -o external/lib_fmod.o
In file included from external/lib_fmod.cpp:1:0:
external/../game_transam.h:13:36: fatal error: external\axl_framework.h: No such file or directory
#include "external\axl_framework.h"
^
compilation terminated.
make: *** [external/lib_fmod.o] Error 1

> Меняем здесь все обратные слэши на прямые.
> OK, пошло.

Зачем он mappyal.c пытается скомпилить? Перемещаем его в папку adime (в external),
чтобы не мешал блин. ОК, дальше:

c++ -w -fpermissive `allegro-config –cflags` -c external/retrospec_highscore.cpp -o external/retrospec_highscore.o
external/retrospec_highscore.cpp: In function ‘size_t WriteMemoryCallback(void*, size_t, size_t, void*)’:
external/retrospec_highscore.cpp:28:50: error: ‘memcpy’ was not declared in this scope
memcpy(&(mem->memory[mem->size]), ptr, realsize);

Блин, в каком инклуде есть этот memcpy? В unistd.h или в stdlib.h? ^
Нет, это как ни странно, в string.h: #include <string.h>

ОК, а вот ошибка сранная вылезла:
c++ -w -fpermissive `allegro-config –cflags` -c external/retrospec_highscore.cpp -o external/retrospec_highscore.o
external/retrospec_highscore.cpp:187:1: error: ‘dest’ does not name a type
dest[pos_dest-added_bytes] = 0;
^
external/retrospec_highscore.cpp:188:1: error: expected declaration before ‘}’ token
}
^
make: *** [external/retrospec_highscore.o] Error 1

В этом файле похоже вообще 2 висячие строки остались.
Комментим их… Да, прошло, но:
c++ -w -fpermissive `allegro-config –cflags` -c external/stringtokeniser.cpp -o external/stringtokeniser.o
external/stringtokeniser.cpp: In member function ‘int StringTokenizer::nextIntToken()’:
external/stringtokeniser.cpp:116:35: error: ‘atoi’ was not declared in this scope
return atoi(nextToken().c_str());
^
external/stringtokeniser.cpp: In member function ‘double StringTokenizer::nextFloatToken()’:
external/stringtokeniser.cpp:122:35: error: ‘atof’ was not declared in this scope
return atof(nextToken().c_str());
^
make: *** [external/stringtokeniser.o] Error 1

В какой либе есть atoi или atof?: #include <stdlib.h>

Да, всё остальное откопилилось без проблем, но линковщик выдал кучу ошибок.

——————————————————————-
adime – одна из них, что это за зверь таков?

Короче, в исходниках она у него не доделана,
берём отсюда: http://adime.sourceforge.net/#download
Инструкции по сборке берем отсюда: http://adime.sourceforge.net/build/linux.txt

Ага, линковщик ругается:
/usr/bin/ld: obj/unix/adimd/adialogf.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC

Надо добавить -fPIC, чтобы это значило?
Ответ Геральда:
In much older versions of the compiler gcc there was a flag "-fPIC" which was an abbreviation for Position Independent Code, and this had to be passed to create library code objects, without that flag, code that is specific to the source would be used, and then the library would fail.

Gerald

Спасибо тебе, Геральд!

ОК, добавим этот самый -fPIC в misc/makefile.uni этого пакета:
CFLAGS += -fPIC

Не помогло, почему-то именно этот злополучный файл компилится без -fPIC
Помогло: добавил -fPIC во все gcc вызовы компиляции.

Опять ошибка:
/usr/bin/ld: cannot find -lalleg-debug
На хер мне дебаг нужен??

ОК, пытаемся рекомпилить с выключенным дебагом:
$ make clean
$ ./fix.sh unix
$ make

Опппаа:
Compiling Adime for UNIX, optimized. Please wait.
gcc -fPIC -DADIME_SRC -Wall -Wno-unused -mcpu=pentium -O2 -funroll-loops -ffast-math -fomit-frame-pointer -fno-strength-reduce -Wno-deprecated-declarations -I./include -o obj/unix/adime/adialogf.o -c src/adialogf.c
gcc: warning: ‘-mcpu=’ is deprecated; use ‘-mtune=’ or ‘-march=’ instead
src/adialogf.c:1:0: error: CPU you selected does not support x86-64 instruction set
/* _ _ _

Зачем он cpu использует? GCC сам определим оптимальный cpu, наверное…
Убираем в makefile.uni -mcpu pentium. У меня давно уже sextium! 🙂

> Урра, теперь всё откомпилиось успешно:
The optimized library for UNIX has been compiled.
Run make install to complete the installation.

Пытаемся поставить в /usr/lib, а не в /usr/local/lib:
$ su
justy adime-2.2.1 # SYSTEM_DIR=/usr make install

OK:
install -m 755 -d /usr/lib
install -m 644 lib/unix/libadime.so /usr/lib/libadime.so
install -m 755 -d /usr/include
install -m 644 include/adime.h /usr/include/adime.h
install -m 755 -d /usr/include/adime
install -m 644 include/adime/adimecfg.h /usr/include/adime/adimecfg.h
install -m 755 -d /usr/include/adime
install -m 644 include/adime/adimeint.h /usr/include/adime/adimeint.h
The optimized UNIX library has been installed.
Run make install-man to install the man pages.
Run make install-info to install the info documentation.
You may conserve space by instead running make install-gzipped-man
and/or make install-gzipped-info.
justy adime-2.2.1 # exit
exit
justy@justy ~/src/retrospec/TranzAm/src/adime-2.2.1 $

Всё с этой ADIME??? Да, ошибки линковщика с adime исчезли, но осталась куча других ошибок!

——————————————————————-

Следующий зверь fblend:https://sourceforge.net/projects/fblend/

Description

Do you think the Allegro blenders are too slow? Do you want to do special
effects in 15/16/32-bpp but can't? Then FBlend is for you! FBlend is
a series of super-fast color blenders for Allegro.
FBlend is anywhere from 4 to 13 times faster than Allegro,

Да,скачиваем zip 2002 года (хо-хо, ой), следуем инстуркциям.
Файл ./fix.sh делаем исполняемым и приводим к Юникс-концам строк в sublime text.

$ ./fix.sh
$ make

ake: *** No rule to make target `/asmdef.c', needed by `obj/unix/asmdef.exe'. Stop.

В фалй make/makefile.lst они забыли добавить файлик asmdef.c, добавляем.
Нет, это не помогло. Да и что за ошибка тупая, какой obj/unix/asmdef.exe?
EXE файлы в DOS и Windows используются, но никак не в Unix/Linux

Убираем этот файлик из lst и ищем дальше.

В инете я наткнулся на адрес:
https://www.allegro.cc/forums/thread/363177
У них такие же проблемы возникали, как и у меня (это 2004 год!), и обсуждение остановилось как раз на этой тупой ошибке.

> ОК, в файле make.makefile.tst в конце в 4 строчках есть упоминания asmdef.exe
Комментируем их, и компиляция продолжается:
gcc -x assembler-with-cpp -c src/x86/cadd16.s -o obj/unix/release/x86/cadd16.o -I. -Isrc -Iinclude
src/x86/cadd16.s: Assembler messages:
src/x86/cadd16.s:33: Error: invalid instruction suffix for `push'

Там стоит pushl. Видимо, ошибка из-за того, что мы пытаемся откомпилить 32-битный код
64-битный компилятором. Попробуем флаг -m32

Добавляем в файл make/makefile.unx в 82-ой строке (где gcc -x assembler-with-cpp) этот флаг:
gcc -m32 -x assembler-with-cpp -c $< -o $@ $(GCC_INCLUDE_PATHS)

Всё, прошло:
justy@justy ~/src/retrospec/TranzAm/src/fblend $ make


gcc -m32 -x assembler-with-cpp -c src/x86/mem_test.s -o obj/unix/release/x86/mem_test.o -I. -Isrc -Iinclude
ar rs lib/unix/libfblend.a obj/unix/release/cadd.o obj/unix/release/mem_test.o obj/unix/release/csub.o obj/unix/release/ctrans.o obj/unix/release/radd.o obj/unix/release/rtrans.o obj/unix/release/2xstretch.o obj/unix/release/fade.o obj/unix/release/x86/cadd16.o obj/unix/release/x86/cadd15.o obj/unix/release/x86/cadd32.o obj/unix/release/x86/csub16.o obj/unix/release/x86/csub15.o obj/unix/release/x86/csub32.o obj/unix/release/x86/trans16.o obj/unix/release/x86/trans15.o obj/unix/release/x86/trans32.o obj/unix/release/x86/radd16.o obj/unix/release/x86/radd15.o obj/unix/release/x86/radd32.o obj/unix/release/x86/rtrans16.o obj/unix/release/x86/rtrans15.o obj/unix/release/x86/rtrans32.o obj/unix/release/x86/2xstretch.o obj/unix/release/x86/fade16.o obj/unix/release/x86/fade15.o obj/unix/release/x86/fade32.o obj/unix/release/x86/mem_test.o
ar: creating lib/unix/libfblend.a

Success!
Now run make install to install FBlend.
————————————————————————

Перед инсталляцией я поменял в фале makefile.unx:
INSTALL_DIR = /usr (вместо /usr/local)

$ sudo make install
cp lib/unix/libfblend.a /usr/lib
cp include/fblend.h /usr/include

FBlend is now installed.

————————————————————————
Возвращаемся в основную ветвь Tranzam, и для линковщика в Makefile добавим: -lfblend
Пробуем!

Неа:
Ошибка с fblend вылезли, но уже другие, типа:
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/libfblend.a(rtrans.o): In function `fblend_rect_trans':
rtrans.c:(.text+0x159): undefined reference to `fblend_rect_trans_mmx_15'
rtrans.c:(.text+0x30e): undefined reference to `fblend_rect_trans_mmx_16'
rtrans.c:(.text+0x321): undefined reference to `fblend_rect_trans_sse_15'
rtrans.c:(.text+0x361): undefined reference to `fblend_rect_trans_mmx_32'
rtrans.c:(.text+0x374): undefined reference to `fblend_rect_trans_sse_16'
rtrans.c:(.text+0x5fc): undefined reference to `fblend_rect_trans_sse_32'
collect2: error: ld returned 1 exit status
make: *** [TranzAm] Error 1

То есть сама либа fblend внеутри себя не может найти функции
касающиеся mmx и sse. Возможно, потому что мы компилили ассемблер с флагом -m32?

Может перекомпилить fblend без них?

OK, fblend хрен с ним, но похоже он использует FMOD3, а не FMODEx, а они отличаются API.

http://www.fmod.org/index.php/release/version/fmodapi375linux.tar.gz
нету, нашел здесь: ftp://ftp.pl.freebsd.org/vol/rzm1/linux-gentoo/distfiles/fmodapi375linux.tar.gz,
но нету x64 версии, а мне она нужна! )))

Что быстрее – переделать вызовы FMOD 3 в FMOD Ex или откопилить прогу в 32 бита?
-m32 включает 32-битный компайлинг?

Сперва пробую перекомпилить fblend в 32-bit:
gcc -m32 -c src/cadd.c -o obj/unix/release/cadd.o -O2 -ffast-math -fomit-frame-pointer -I. -Isrc -Iinclude
In file included from /usr/include/errno.h:28:0,
from /usr/include/allegro/base.h:24,
from /usr/include/allegro.h:25,
from src/cadd.c:17:
/usr/include/features.h:374:25: fatal error: sys/cdefs.h: No such file or directory
# include <sys/cdefs.h>
^
compilation terminated.
make: *** [obj/unix/release/cadd.o] Error 1

Надо также доустанавливать 32-битные либы:
apt-get install gcc-multilib
и apt-get install g++-multilib libc6-dev-i386

Да, fblend устновлися вроде нормально.
Теперь пробуем adime.

Ага, подключили флаги -m32, откомпилися ОК, выдал вот что:
gcc -s -shared -o lib/unix/libadime.so obj/unix/adime/adialogf.o obj/unix/adime/adime.o obj/unix/adime/calcedit.o obj/unix/adime/dbool.o obj/unix/adime/dbutrow.o obj/unix/adime/dbutton.o obj/unix/adime/dchain.o obj/unix/adime/ddialogf.o obj/unix/adime/dfilenam.o obj/unix/adime/dfloat.o obj/unix/adime/dgreybol.o obj/unix/adime/dinteger.o obj/unix/adime/dline.o obj/unix/adime/dlists.o obj/unix/adime/dnothing.o obj/unix/adime/dpfloat.o obj/unix/adime/dpintege.o obj/unix/adime/dstring.o obj/unix/adime/fsel.o obj/unix/adime/gui.o obj/unix/adime/eval.o obj/unix/adime/keynames.o obj/unix/adime/nan.o obj/unix/adime/parsemod.o obj/unix/adime/register.o `allegro-config –libs release –shared` -m32
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/liballeg.so when searching for -lalleg
/usr/bin/ld: cannot find -lalleg
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libc.so when searching for -lc
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libc.a when searching for -lc
collect2: error: ld returned 1 exit status
make: *** [lib/unix/libadime.so] Error 1

Да, ему нужна в частности 32-битная либа allegro. А как её поставить на x86_64 machine?

Скачал deb и установил отюда:
https://launchpad.net/ubuntu/+source/allegro5/2:5.0.11-1/+build/7389169

liballegro5.0_5.0.11-1_i386.deb
liballegro5-dev_5.0.11-1_i386.deb

Да, тут неувязочска выходит. Дев пакет не ставится, ему мешает аллегро4-дев.
Но он также зависит от ряда других пакетов, а у меня стоят только их 64-битные аналоги,
то есть по идее мне нужно устанавливать 32-битные аналоги этих пакетов.

Проще в FMOD разобраться!

Итак, я перекомпилил
adime-2.2.1
fblend (отключил MMX и SSE в include/mmx.h include/sse.h),
так что ассемблерный код совсем не компилися.

$ sudo make install
cp lib/unix/libfblend.a /usr/lib
cp include/fblend.h /usr/include

FBlend is now installed.

Да, нашел minifmod в течение нескольких часов,
теперь пытаюсь скомпилить его вместе с проектом.

Ошибка gcc – не распознаёт констанут __LINUX__,
ему только __linux__ нужна?

В gcc добавляю флаг -D__LINUX__ Очуметь, прошло дальше но на ассемблрном коде запнулось:

gcc -D__LINUX__ -w -fpermissive `allegro-config –cflags` -c -o external/minifmod/mixer_clipcopy.o external/minifmod/mixer_clipcopy.c
external/minifmod/mixer_clipcopy.c: Assembler messages:
external/minifmod/mixer_clipcopy.c:42: Error: incorrect register `%rsi' used with `l' suffix
external/minifmod/mixer_clipcopy.c:53: Error: incorrect register `%rdi' used with `l' suffix
external/minifmod/mixer_clipcopy.c:54: Error: incorrect register `%rcx' used with `l' suffix
make: *** [external/minifmod/mixer_clipcopy.o] Error 1

удаляем (комментируем) 20 строку в mixer_clipcopy.c
#define USE_ASM_FOR_CLIPCOPY
чтобы он не использовал ассемблер.

Вылезла ещё тупая ошибка:
gcc -D__LINUX__ -w -fpermissive `allegro-config –cflags` -c -o external/minifmod/mixer_clipcopy.o external/minifmod/mixer_clipcopy.c
external/minifmod/mixer_clipcopy.c: In function ‘FSOUND_MixerClipCopy_Float32’:
external/minifmod/mixer_clipcopy.c:34:30: error: lvalue required as increment operand
int val = *((float *)src)++;
^
external/minifmod/mixer_clipcopy.c:35:21: error: lvalue required as increment operand
*((short *)dest)++ = (val < -32768 ? -32768 : val > 32767 ? 32767 : val);
^
make: *** [external/minifmod/mixer_clipcopy.o] Error 1

GCC 4 не разрешает такие вещи, что разрешал GCC 3
Итак, я ставлю g++3.3:
sudo apt-get install g++-3.3

попробую им сейчас всё скомпилить, тольо кбурать флаг -fpermissve надо будет?!
Он мне поставил CLANG (clang) – замена GCC (зачем?),
но этот тупица выдал ту же ошибку про lvalue

ОК, возвращаюсь к GCC (русть clang остётся, но зачем он нужен?)

Исправил эти две строки, разбил их на более простые с присвоением указателей.

Пошло, minifmod откомпилися!

Но опять же ошибки поехали в lib_fmod.cpp:
gcc -D__LINUX__ -w -fpermissive `allegro-config –cflags` -c external/lib_fmod.cpp -o external/lib_fmod.o
In file included from external/../game_transam.h:22:0,
from external/lib_fmod.cpp:1:
external/../external/lib_fmod.h:8:1: error: ‘FSOUND_STREAM’ does not name a type
FSOUND_STREAM* PlaySampleFromStream(const char* filename, int& channel,int volume=-1, long length=0, long additionalmode=0);
^
external/../external/lib_fmod.h:9:17: error: variable or field ‘StopStream’ declared void
void StopStream(FSOUND_STREAM* fs);
^
external/../external/lib_fmod.h:9:17: error: ‘FSOUND_STREAM’ was not declared in this scope
external/../external/lib_fmod.h:9:32: error: ‘fs’ was not declared in this scope
void StopStream(FSOUND_STREAM* fs);

Очуметь, оказывается в этом minifmod нет FSOUND_STREAM!
Да, похоже minifmod тут не подойдет – нет FSOUND_STREAM

Придётся с FMOD3 на FMODEx всё же переделывать!
Поиск google: fmod3 fmodex
Здесь полезная инфо: http://www.fmod.org/questions/question/forum-33249

Wine мне открыл fmodex.chm и я нашёл секцию TRANSITIONING BETWEEN FMOD 3 AND FMOD EX. API DIFFERENCES

Скопировал текст статьи, открыл LibreOffice Write, вставил туда текст
(получлось красиво 2 листа), распечатал их. Красота!
Сейчас буду изучать и переделывать код lib_fmod.cpp на FMODEX!

Музыку почти переделал, только не пойму где аналог FMUSIC_SetOrder под FMOD 4?
Чтобы это значило?
В документации написано:
Sets a songs order position / current playing position.

Что означает сия позиция? Что она даёт?? Это позиция отностилеьно чего?

Ладно, пока оставляем её в покое, двигаемся дальше.
Если что, вернемся к этому позднее.

Стоп, так он закомментирован, поэтому по любому двигаемся дальше!

Так, уже 18 мая, перделал lib_fmod с FMOD 3 на FMOD Ex (FMOD 4)
Исправил ещё кучу ляпов и вызовов старого fmod в game_*.cpp файлах.

Добавил функцию (помиомо некоторых прочих) UpdateSound()
и вызываю её в WinGameLogic() в файле game_wingame.cpp,
как того требует документацию к FMOD Ex.

Пробуем компилить, ох, линковщика я опасаюсь!

Охх, очередной FMOD'освский старый ляп вышел (в послденем файле проекта!):
gcc -D__LINUX__ -w -fpermissive `allegro-config –cflags` -c game_wingame.cpp -o game_wingame.o
game_wingame.cpp: In function ‘void GameEndInitialiseEndScreen()’:
game_wingame.cpp:110:41: error: ‘FMUSIC_SetMasterSpeed’ was not declared in this scope
FMUSIC_SetMasterSpeed(ActiveMusic,0.8);
^
Что за FMUSIC_SetMasterSpeed() ? Сейчас будем разбираться…

Делаем функцию SetSpeedTrackerSong в lib_fmod'е и вызываем её в game_wingame.cpp
вместо FMUSIC_SetMasterSpeed. ActiveMusic мы тут убираем, так она она одна, и так ясно.

Тем более в FMOD Ex есть подобная функция FMOD_Sound_SetMusicSpeed

Последний $ make!

Да, линкер ругается:
g++ external/axl_animations.o external/axl_config.o external/axl_framework.o external/funkyfont.o external/lib_fmod.o external/mappyal.o external/retrospec_highscore.o external/stringtokeniser.o external/tinystr.o external/tinyxml.o external/tinyxmlerror.o external/tinyxmlparser.o external/water.o game_astar.o game_car.o game_credits.o game_game.o game_help.o game_highscore.o game_levels.o game_logo.o game_menu.o game_particles.o game_pause.o game_ScrollingText.o game_startcountdown.o game_transam.o game_vars.o game_wingame.o -o TranzAm -lpthread -lfmodex64 -ladime -lfblend `allegro-config –libs` `curl-config –libs`
game_car.o: In function `Car::SetCurrentState()':
game_car.cpp:(.text+0x464): undefined reference to `MapChangeLayer'
game_car.cpp:(.text+0x487): undefined reference to `MapGetBlockInPixels'
game_car.cpp:(.text+0x534): undefined reference to `MapChangeLayer'

Какую либу я забыл присобачить в -l ?
Сейчас поищем в интернете эти функции.

А, нет, это вылезло видимо от того, что для компиляции мы испорльзовали gcc,
а для сборки – g++.

Я сейчас исправил это всё на gcc, и вылезла уже другая ошибка линковщика, но всего одна! Уррра!

gcc external/axl_animations.o external/axl_config.o external/axl_framework.o external/funkyfont.o external/lib_fmod.o external/mappyal.o external/retrospec_highscore.o external/stringtokeniser.o external/tinystr.o external/tinyxml.o external/tinyxmlerror.o external/tinyxmlparser.o external/water.o game_astar.o game_car.o game_credits.o game_game.o game_help.o game_highscore.o game_levels.o game_logo.o game_menu.o game_particles.o game_pause.o game_ScrollingText.o game_startcountdown.o game_transam.o game_vars.o game_wingame.o -o TranzAm -lpthread -lfmodex64 -ladime -lfblend `allegro-config –libs` `curl-config –libs`
/usr/bin/ld: external/axl_animations.o: undefined reference to symbol '_ZSt28_Rb_tree_rebalance_for_erasePSt18_Rb_tree_node_baseRS_@@GLIBCXX_3.4'
//usr/lib/x86_64-linux-gnu/libstdc++.so.6: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make: *** [TranzAm] Error 1

Что за _ZSt28_Rb_tree_rebalance_for_erasePSt18_Rb_tree_node_baseRS_ ?
Ёперный театр, я не выговорить это не могу, не то что написать!

Перетасовал -l в Makefile, получилась другая немного ошибка:
/usr/bin/ld: external/funkyfont.o: undefined reference to symbol 'cos@@GLIBC_2.2.5'
//lib/x86_64-linux-gnu/libm.so.6: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status

Уже cos ему не нравится, но это полегче, чем _ZSt28_Rb_tree_rebalance_for_erasePSt18_Rb_tree_node_baseRS_

Так мой же ответ здесь есть:
http://stackoverflow.com/questions/23809404/issue-with-simple-makefile-undefined-reference-to-symbol-cosglibc-2-2-5

"Also try to use c++ instead of gcc compiler. It includes this library by default."

Вот ещё инфо по этому вопросу:
use g++ to compile C++ programs, it'll link in the standard c++ library. gcc will not. gcc will also compile your code as C code if you give it a .c suffix. Give your files a .cpp suffix.

Сейчас попробуем переключиться на c++ и пересобрать проект!

Нет, линковщик стал ругаться на либы типа MapChangeLayer, MapGetBlockInPixels и подобные.
Они все находятся в mappyal.cpp, то есть мы неверно его подключаем?

Ага, в mappyal.h я нашел такую штуку:
#ifdef __cplusplus
extern "C" {
#endif

В других файлах проекта такой штуки нет, значит – убираем её???

Да, сделал make clean && make (может можно использовать make -B?)
и вылезло уже всего две жалобы линкера:
game_game.o: In function `LoadLevel()':
game_game.cpp:(.text+0x29fc): undefined reference to `MapLoadVRAM(char*)'
game_game.cpp:(.text+0x2b8e): undefined reference to `MapLoad(char*)'
collect2: error: ld returned 1 exit status
make: *** [TranzAm] Error 1

Это уже получше, вместо нескольих десятков в прошлый раз.
Ищем эти функции в mappyal.cpp и в mappyal.h.
Ага, видем несоответсие. Они объявлены в mappyal.h как char *,
а в mappyal.cpp как unsigned char *

Исправляем на unsigned char * в mappyal.h, make -B пробуем!

Ооо, компиляция удалась:
……
……
c++ -D__LINUX__ -w -fpermissive `allegro-config –cflags` -c game_vars.cpp -o game_vars.o
c++ -D__LINUX__ -w -fpermissive `allegro-config –cflags` -c game_wingame.cpp -o game_wingame.o
c++ external/axl_animations.o external/axl_config.o external/axl_framework.o external/funkyfont.o external/lib_fmod.o external/mappyal.o external/retrospec_highscore.o external/stringtokeniser.o external/tinystr.o external/tinyxml.o external/tinyxmlerror.o external/tinyxmlparser.o external/water.o game_astar.o game_car.o game_credits.o game_game.o game_help.o game_highscore.o game_levels.o game_logo.o game_menu.o game_particles.o game_pause.o game_ScrollingText.o game_startcountdown.o game_transam.o game_vars.o game_wingame.o -o TranzAm `curl-config –libs` `allegro-config –libs` -lfmodex64 -ladime -lfblend
o If there are no errors, TranzAm compiled succesfully

Что странно, так как я заметил краем глаза в MapLoadABM такой же косяк,
но линкер почему то его пропустил?
Скорее всего, это потому что не было вызова его извне. Будет – невнимательный косяк возникнет.

Итак, смотрим, что у нас получилось:
justy@justy ~/src/retrospec/TranzAm/src/src $ cp TranzAm ../..
justy@justy ~/src/retrospec/TranzAm/src/src $ cd ../..
justy@justy ~/src/retrospec/TranzAm $ ./TranzAm

Ууупс, чёрный дисплей, всё повисло. Ни на что не реагирует.
Но это линукс, его убить не так-то легко.

Я залогинся на другом tty (Ctrl+Alt+F1) – можно выбирать любой от F1 до F6
На Ctrl+Alt+F8 у нас висят X + Cinnamon, на Ctrl+Alt+F7 сообщения ядра, что ли, не пойму.
Они появлялись, только когда я пару раз переключился на этот tty.

Итак, залонигился на tty1 под рутом, нажал w, увидел висящий процесс ./TranzAm,
убил его killall TranzAm, потом переключился на tty8 и выставил разрешение экрана обычное
(игра мне его сбила). Если окна не видно, я использую Alt+F7 shorcut для сдвига окна в центр.

Уупс, видим ошибку:
*** Error in `./TranzAm': malloc(): memory corruption: 0x0000000002064130 ***
Aborted

Блин, где она? Использовать gdb? Я с 2008 года его не использовл, уже забыл как там и что!

Подключаем -lpthread в Makefile и пытаемся пересобрать проект:
$ make -B

Не помогло. Видимо, ошибка возникает здесь:
this->GameAnimationLibrary=new AnimationLibrary(AnimationFile, GameConfiguration->CapsSystem.fps,maxtype, BitmapCreator);

Нашёл, где он запинается:
//Now we have a proper mask structure allocated and mostly initialized, but the mask data has garbage! We have to initialize it to 0's:
for(INTVAR=maskout->h-1; INTVAR>=0; INTVAR–) {
for(INTVAR2=maskout->max_chunk; INTVAR2>=0; INTVAR2–) {
maskout->sp_mask[INTVAR][INTVAR2]=0;
}
}

в axl_animations.cpp

Здесь:
//Now that we have some more data, we allocate the mask data…
maskout->dat = malloc( (maskout->max_chunk+1) * 4 * Image->h );

Сделал * 8 и игра заработала, правда как-то кривова-то. Некоторые спрайты плывут,
некоторых вообще не видно. Зато музыка играет и некоторые эффекты!

И сама игра заверашется Segmentation fault!

Попробую использовать OpenLayer, ставлю новые пакеты:
liballeggl4.4:amd64 (2:4.4.2-4) …
libopenlayer2 (2.1-1) …
libopenlayer-dev (2.1-1) …

И ещё доставил: liballeggl4-dev (2:4.4.2-4) ..

В файле axl.h ставлю #define USE_OPENLAYER 1 (было 0)

Такая ошибка:

/usr/include/OpenLayer/Glyph.hpp:13:22: fatal error: ft2build.h: No such file or directory
#include <ft2build.h>
^
compilation terminated.
make: *** [external/axl_animations.o] Error 1

ОК, компиляция нужна с freetype, подключаем его для GCC:
CFLAGS: `freetype-config –cflags`
LDFLAGS: `freetype-config –libs`

Но вылезли тупые ошибки, откуда???:
external/axl_animations.h:224:8: error: expected unqualified-id before numeric constant
void DestroyAll();

external/axl_animations.cpp:1429:13: error: expression cannot be used as a function
DestroyAll();

external/axl_animations.cpp: At global scope:
external/axl_animations.cpp:1456:24: error: expected unqualified-id before numeric constant
void AnimationLibrary::DestroyAll()

В .h файле стояло:
AXL_BITMAP* GetFirstGraphic(const std::string& id) const;
void DestroyAll();
void draw() const;

Может ему не нравится const; на конце? Но почему ранее это прокатывалао?

ОК, отключаю openlayer, будем разбираться с тем что есть.
Кстати, для компиляции с openlayer также применяется связка
openlayer-config –cflags openlayer-config –libs : НА БУДУЩЕЕ!

Оказывыается в корне есть файлик config.xml, здесь можно настроить легко windowed режим окна,
работает иногда, но вылетает что-то.

———————————————————————————————
ОК, перехожу к компиляции JJ.
Удалил из корня три исходных файла – они все есть в дире sources.
mv sources src
Сделал все имена файлов маленькими буквами, а то опять файлы не находятся GCC.
Скопировал Makefile от Alien8, сделал некоторые изменения (c->cpp, TARGET->ff,
убрал лишние либы, тут кроме аллегро похоже ничего не примаенятеся и слава Богу)

Итак: любимый make
c++ -w `allegro-config –cflags` -c main.cpp -o main.o
main.cpp: In member function ‘virtual void CAllegro::init_game()’:
main.cpp:115:18: error: ‘GFX_GDI’ was not declared in this scope
if(set_gfx_mode(GFX_GDI,SVGA_W,SVGA_H,0,0)<0) abortsystem("Cannot set/reset 640×480 8 bit mode!")

Mon May 18 20:18:45 MSK 2015
Блин, что с этим GFX_GDI не так? Может не та версия Аллегро опять? Сейчас погуглю немного…

Ааа, это только для Windows режим! Прописан в файлике /usr/include/allegro/platform/alwin.h

Поэтому меняем на GFX_AUTODETECT!

ОК:
sh_alleg.cpp:6:22: fatal error: iostream.h: No such file or directory
#include <iostream.h>
^
Поменял на #include <iostream>, посмотрим, что получится:
jj compiled succesfully

$ cd ..
$ ./jj

Игра играет только без музыки и звука почему-то?!
Запустил виндовый вариант под wine, музыки нет, а эффекты есть
(в настройках прописано и то и другое, я проверял)

======================================================================================
Ладно, попробуем jjwf (или jjws, виндовый файл называется jjws.exe почему-то, опечятка?)

Проводим почти те же манипуляции, что и с jj. Используем Makefile т jj.
TARGET = jjwf

$ make
c++ -w `allegro-config –cflags` -c game.cpp -o game.o
game.cpp:1162:4: error: missing terminating " character
char code[256]="ZX82;
^
game.cpp: In function ‘int playerUpdate()’:
game.cpp:1163:4: error: expected primary-expression before ‘int’
int scores[1]={thescore};
^
make: *** [game.o] Error 1

> И сразу же ошибка. Сразу видно опечятку, пропущена закрывающая кавычка. Исправляем.
ОК, пошло дальше:
sh_alleg.cpp:6:22: fatal error: iostream.h: No such file or directory
#include <iostream.h>

Такая же туфта с iostream. Убираем .h, надеемся что namespace std нам не помешает…

jjwf compiled succesfully

Игра запустилась, такая же почти как jj, звука/музыки опять же нет.
Да, игра сложная, первый уровень даже пройти не могу.
Почему они делают первые уровни такими сложными???

==============================================================
Ладно, пробуем styx
Сразу используем Makefile от jjwf, выходит такая же ошибка с iostream – правим.

c++ Game.o Intro.o Main.o My_sprit.o Sh_alleg.o Sh_sprit.o -o styx `allegro-config –libs`
styx compiled succesfully

Запускаем из диры выше!
Игра играет без звука. Прикольная, но туповатя…

====================================================================
И посденяя из списка retrospec: Isomot.
Это либа, которая может применяться в проектах.

Скомпилил демо-проект в папке Demo (IsomotDemo0Eng.c).
Удалил испанскую версию файла, а то линковщик ругался на двойной main.

Так же использовал gcc и -lm для сборки проекта.

isomot_demo compiled succesfully

Жаль, retrospec не даёт исходники Exolon, JetSetWilly, Head over Heels,
вот это игрушки крутые!
Их бы скомпилить.

——————————–
ЛаднО, попробую скомпилить AXL_project и демки к нему.

Wed May 20 09:43:09 MSK 2015
Создал папку src, туда в папке axl скопировал файлы AXLAnimations.
Подключил 4 теста из animations/example*

Подправил соотв. Makefile для компиляции одного main.cpp из папки test*/

Скомпилил достаточно быстро, подправив некоторые пути к включаемым файлам.
Та же ошибка malloc(): memory corruption: 0x0000000001fa17d0 ***

Это недостаточное выделение памяти в axl/axl_animations.cpp
строка 1095: maskout->dat = malloc( (maskout->max_chunk+1) * 4 * Image->h );

* 4 меняем на * 8.
Компилим, запускаем.

Ура, test1 запустился. Но я хочу переделать Makefile так, что бы он собирал несколько
программ за раз.

Ищем инфо, нашел первый сайт:
http://stackoverflow.com/questions/5950395/makefile-to-compile-multiple-c-programs

Да, всё получилось, test1..test4 скомпилились в .elf файлы и запустились.
При нажатии 'd' один раз вылетел с Segmentation fault

Wed May 20 11:56:58 MSK 2015
Всё, наигрался, всё получилось, больше вроде не вылетало.
Чтож тогда tranzAm вылетает?

И не смог избавиться от удаления .o после сборки. Я не хочу их удалять!
Всё, погугили, понял – это станадартное поведление make.
Надо их в правило пустое включить, чтобы не удалялись,

That is not what -pedantic is for. -pedantic will remove any non-ansi features that even -ansi permits.
-Werror will change warnings to errors. – jtniehof May 10 '11 at 14:09

Note that if you want both programs to be built automatically, the all target must appear before the individual programs in the makefile, and be the first target in the makefile. – Randall Cook Jan 8 '14 at 2:15

=================================================================

Возвращаюсь к TranzAm.
Пересоберу проект с -g -ggdb3

Опппаа, помните, не было звука Аллегро?
Я нашёл в пакетах liballegro4.4-plugin-alsa:amd64
и в описании:
This plugin adds support for ALSA to the Allegro library. It is recommended
on Linux. If no audio plugin package is installed, OSS is used for audio.

Так OSS уже давно устарело, какого они его используют?
Может сейчас звук зарабоатет в играх с аллегро?

Да, заработал! Поразительно, как такое может быть??? Кааак?

Это же Линукс, блин! Но почему, почему?

Зачем они по умолчанию используют OSS, которая много лет назад устарела,
ав не используют ALSA по-умолчанию, которая уже много лет в линукс в фавритах?
Почему? И ведь это Аллегро 4 у меня установился по-умолчанию,
я вижу в репозитории Аллегро-5, но он почему-то не поставился по умолчанию мне.

ОК. Просто поставьте liballegro4.4-plugin-alsa:amd64 и у Вас заработает звук в Аллеграо-играх!

Итак, потерял много часов с этим TransAm, боролся с исходниками, потом с линковщиком.
Потом с AdiMe – всё же решил использовать внешние либы.
Потом с FBLEND – непонятно, даже когда USE_FBLEND=0 он использует функции
void fblend_rect_trans(BITMAP *dst, int x, int y, int w, int h, int color, int fact);
void fblend_trans(BITMAP *src, BITMAP *dst, int x, int y, int fact);
Я сделал их DUMMY, но всё равно вылетает где-то в funkyfont.cpp.

Блин, надо попробовать в 32- разрядной системе скомпилировать всё это добро!

Для этого мне нужен VirtualBox!

Вот собрал на 2-ой день TransAm32:

/usr/lib/gcc/i686-linux-gnu/4.8/../../../../lib/libfblend.a(rtrans.o): In function `fblend_rect_trans':
rtrans.c:(.text+0x161): undefined reference to `fblend_rect_trans_mmx_15'
rtrans.c:(.text+0x2fa): undefined reference to `fblend_rect_trans_mmx_16'
rtrans.c:(.text+0x32b): undefined reference to `fblend_rect_trans_sse_15'
rtrans.c:(.text+0x387): undefined reference to `fblend_rect_trans_mmx_32'
rtrans.c:(.text+0x3b8): undefined reference to `fblend_rect_trans_sse_16'
rtrans.c:(.text+0x619): undefined reference to `fblend_rect_trans_sse_32'
collect2: error: ld returned 1 exit status
make: *** [TranzAm] Error 1
ubu@ubu-VirtualBox:~/src/TranzAm/src$ sudo rm /usr/lib/gcc/i686-linux-gnu/4.8/../../../../lib/libfblend.a
[sudo] password for ubu:
ubu@ubu-VirtualBox:~/src/TranzAm/src$ make
c++ external/axl_animations.o external/axl_config.o external/axl_framework.o external/funkyfont.o external/lib_fmod.o external/mappyal.o external/retrospec_highscore.o external/stringtokeniser.o external/tinystr.o external/tinyxml.o external/tinyxmlerror.o external/tinyxmlparser.o external/water.o game_astar.o game_car.o game_credits.o game_game.o game_help.o game_highscore.o game_levels.o game_logo.o game_menu.o game_particles.o game_pause.o game_ScrollingText.o game_startcountdown.o game_transam.o game_vars.o game_wingame.o -o TranzAm -lfmod-3.75 -ladime -lfblend `curl-config –libs` `allegro-config –libs`
!! TranzAm compiled succesfully
mv TranzAm ..

То есть ошибка линковщика в данном случае решилась удалнием файла
/usr/lib/gcc/i686-linux-gnu/4.8/../../../../lib/libfblend.a

Но он остался:
ubu@ubu-VirtualBox:~/src/fblend$ find libfblend
find: `libfblend': No such file or directory
ubu@ubu-VirtualBox:~/src/fblend$ locate libfblend
ubu@ubu-VirtualBox:~/src/fblend$ sudo updatedb
ubu@ubu-VirtualBox:~/src/fblend$ locate libfblend
/home/ubu/src/fblend/lib/mingw32/libfblend.a
/lib/libfblend.a

Только звука нет и клава криво работает! )))
Это скорее всего из-за виртуалки.

Но переходы работают нормально и шрифт показывает нормально и игра не вылетает!

Клава вылечилась отключением джойстика в config.xml

А вот звук попробую virtualBox с pulseaudio на ALSA переключить…
Не-а, не работает, хотя в системе вроде звук есть, я ч/з настройки Audio проверил.

========================

ОК, решил всё же пересобрать TranzAm с флагом -m32
Ошибка: (привключении #include <string>)
/usr/include/c++/4.8/string:38:28: fatal error: bits/c++config.h: No such file or directory
#include <bits/c++config.h>

лечится видимо:
$ sudo apt-get install gcc-4.8-multilib g++-4.8-multilib
[sudo] password for justy:
Reading package lists… Done
Building dependency tree
Reading state information… Done
gcc-4.8-multilib is already the newest version.
gcc-4.8-multilib set to manually installed.
The following extra packages will be installed:
lib32stdc++-4.8-dev lib32stdc++6 libx32stdc++-4.8-dev libx32stdc++6
Suggested packages:
lib32stdc++6-4.8-dbg libx32stdc++6-4.8-dbg
The following NEW packages will be installed:
g++-4.8-multilib lib32stdc++-4.8-dev lib32stdc++6 libx32stdc++-4.8-dev
libx32stdc++6
0 upgraded, 5 newly installed, 0 to remove and 10 not upgraded.

!!! Да, компиляция прогла успешно,
я установил тогда gcc-4.8-multilib, а про g++-4.8-multilib забыл!

Но линкер выдал ошибку:
/usr/bin/ld: skipping incompatible /lib/../lib/libfmod-3.75.so when searching for -lfmod-3.75
/usr/bin/ld: skipping incompatible //lib/libfmod-3.75.so when searching for -lfmod-3.75
/usr/bin/ld: cannot find -lfmod-3.75
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/libadime.so when searching for -ladime
/usr/bin/ld: skipping incompatible /usr/lib/../lib/libadime.so when searching for -ladime
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../libadime.so when searching for -ladime
/usr/bin/ld: skipping incompatible //usr/lib/libadime.so when searching for -ladime
/usr/bin/ld: cannot find -ladime
collect2: error: ld returned 1 exit status
make: *** [TranzAm] Error 1

Оппа, я линкер без -m32 запускаю, сейчас поправлю.
Не нашёл либы 32bit для cvurl и fblend.
Всё верно, у меня их нет, сейчас с Юбунты скопирую.

Всё, скомпилилось. Линкер пожаловался:
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.so when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.so when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libc.so when searching for -lc
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libc.a when searching for -lc
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libc.so when searching for -lc
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libc.a when searching for -lc
!! TranzAm compiled succesfully

Но в итоге все скомилировалось и работает, правда, без звука.
Сейчас передалем с FMOD 3 на FMOD Ex (FMOD 4)

Итак, заменяем файлы lib_fmod.h и lib_fmod.cpp в папке external
(из прошлого проекта, где мы переделывали FMOD 3 в FMOD EX),
удаляем отсюда файлы fmod.h и fmod_errors.h

В файле game_transam.h удаляем external в ссылках на эти файлы

Все вхождения FSOUND_STREAM и FMUSIC_MODULE меняем на FMOD_SOUND

В game_car.cpp меняем FSOUND_LOOP_* на FMOD_LOOP,
для переменных int, относящиеся к каналам (начинаются на playing)
делаем тип FMOD CHANNEL *. И нормализуем их в соотв. с этим (NULL)

В game_car.h originalCarNoiseFrequency тип меняем на float.
Делаем правильный расчёт его.

game_game.cpp: тот же loop и замена звук. канала playingRadarBeep
FSOUND_StopSound(FSOUND_ALL) меняем на StopSFX(FSOUND_ALL);

ДАЛЕЕ:
game_logo.cpp:21:8: error: ‘FSOUND_STREAM’ does not name a type
Меняем на FMOD_SOUND, нормализуем обращения к функции PlaySampleFromStream

game_menu.cpp:566:72: error: ‘FSOUND_SetSFXMasterVolume’ was not declared in this scope

game_pause.cpp:4:8: error: ‘FSOUND_STREAM’ does not name a type
Он не используется (пока?)
а FMUSIC_SetPaused(ActiveMusic,FALSE); меняем на PauseTrackerSong(FALSE);

game_transam.cpp: 3 ошибки
FMUSIC_StopAllSongs -> RemoveSound();
FMUSIC_SetPaused -> PauseTrackerSong;

И наконец, game_vars.cpp:100:1: error: ‘FMUSIC_MODULE’ does not name a type
FMUSIC_MODULE *ActiveMusic=NULL;
^
game_vars.cpp:103:1: error: ‘FSOUND_SAMPLE’ does not name a type
FSOUND_SAMPLE *snd_menuchange = NULL;

Надо заменить всё на FMOD_SOUND!

game_wingame.cpp:110:41: error: ‘FMUSIC_SetMasterSpeed’ was not declared in this scope
FMUSIC_SetMasterSpeed(ActiveMusic,0.8);

меняем на SetSpeedTrackerSong(0.8);

Всё, заработало! Музыка есть, шрифт виден, переходы нормальные.
Круто!
Но иногда выдёт в конце по завершении: Segmentation fault

Найти будет не трудно, а оно надо?
Скорее всего где-то я с каналами намудрил или ещё что.

Да, звуковые эффекты плохо проявляются, точнее их совсем почти нет.
Только в меню и при столкновении, но при стокновении не полный.
Будем лечить? А оно надо?

Да, нашёл несколько ляпов в PlaySFX – неверное использование FMOD_LOOP_* и каналов.

Что-то звук есть ког-где, но в шуме мотора его нет.

ОК, нашел баг в AdjustVolumeSFX
У меня было: volume / 255, а надо было (float)volume / 255
С++ не умеет автоматом приводить к float, даже когда результат должен быть float.
Это тебе не PHP, дружок.

ОК, звук работает, но глюк в том, что звук мотора и звук конца бензина не затихают!
То есть не работают функции StopSFX? Может, в группе глючит?

У меня просто каналы теряются. А так всё ОК, прекрасная маркиза!
Да, потому что я забыл создать группу каналов, которую использую,
в функции InitialiseSound:
FMOD_System_CreateChannelGroup(fmodSystem, NULL, &fmodEffects);

Всё, теперь звуки работают 100%! Как в виндовой версии!

И ещё я хотел сделать так, чтобы после окончании мини-игры меню возращалось в выбор карты, а не в главное.
Как это сделать? Это я сделал: (закомментировал 2 строки в файле game_menu.cpp)
if(currentLevel)
{
// CurrentTopMenu=0;
// CurrentMenuItem=0;

Initialised=false;

Один глюк – неверное ADIME? меню в выборе карты для мини-игры:
Хочу перекомпилить ADIME библиотеку (Allegro Dialogs Made Easy)
для 64 и 32 разряда.

Итак, находим и распаковываем adime-2.2.1.tar.gz
Пишем:
$ ./fix.sh unix
$ make

Сразу вылезла ошибка:
gcc -DADIME_SRC -Wall -Wno-unused -mcpu=pentium -O2 -funroll-loops -ffast-math -fomit-frame-pointer -fno-strength-reduce -Wno-deprecated-declarations -I./include -o obj/unix/adime/adialogf.o -c src/adialogf.c
gcc: warning: ‘-mcpu=’ is deprecated; use ‘-mtune=’ or ‘-march=’ instead
src/adialogf.c:1:0: error: CPU you selected does not support x86-64 instruction set
/* _ _ _
^
make: *** [obj/unix/adime/adialogf.o] Error 1

Находим строку mcpu, убираем её.
/usr/bin/ld: obj/unix/adime/adialogf.o: relocation R_X86_64_32S against `adime_d_multiline_text_proc' can not be used when making a shared object; recompile with -fPIC
obj/unix/adime/adialogf.o: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
make: *** [lib/unix/libadime.so] Error 1

В misc/makefile.uni добавим два флага:

COMPILE_FLAGS += -fPIC
COMPILE_FLAGS_NO_OPTIMIZE += -fPIC

и всё в ажуре!
$ sudo make install
[sudo] password for justy:
install -m 755 -d /usr/lib
install -m 644 lib/unix/libadime.so /usr/lib/libadime.so
install -m 755 -d /usr/include/adime
install -m 644 include/adime/adimecfg.h /usr/include/adime/adimecfg.h
install -m 755 -d /usr/include/adime
install -m 644 include/adime/adimeint.h /usr/include/adime/adimeint.h
The optimized UNIX library has been installed.
Run make install-man to install the man pages.
Run make install-info to install the info documentation.
You may conserve space by instead running make install-gzipped-man
and/or make install-gzipped-info.

ОК, это версия 64 бит, теперь попробуем собрать 32 бит.
Добавляем флаг -m32 там где мы добавляли -fPIC

ОК, линкер запнулся:
/usr/bin/ld: i386 architecture of input file `obj/unix/adime/adialogf.o' is incompatible with i386:x86-64 output
/usr/bin/ld: i386 architecture of input file `obj/unix/adime/adime.o' is incompatible with i386:x86-64 output

Да я просто для линкера заблы добавить этот флаг: -m32

Опять выдал ошибку:
gcc -s -o examples/exanim obj/unix/adime/exanim.o lib/unix/libadime.so `allegro-config –libs release –shared`
lib/unix/libadime.so: error adding symbols: File in wrong format
collect2: error: ld returned 1 exit status

Но файл lib/unix/libadime.so есть, и он 32 битный:
$ file lib/unix/libadime.so
lib/unix/libadime.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, BuildID[sha1]=b4c6aa0171f446aaee9591ab552923765615186c, stripped

-s флаг добавил, а -m32 – нет
Добавляем ещё строчку в makefile.uni:
(рядом с соотв. строками)
LFLAGS += -m32

Всё, теперь make отработал до конца.

Итак, послдений шаг:
$ sudo cp lib/unix/libadime.so /usr/lib/i386-linux-gnu/

Пересобрал TranZam, а глюк с меню тот же остался.
Косяк в либе ADIME, где-то в функции adime_dialogf
Мне, сейчас всю либу переделывать?
Может проще написать свой диалог?

В принципе, TranZam готов на 99% –
игра играет, музыка звучит, эффекты все есть.

Что надо исправить для полного выпуска:
1. Исправить диалог Adime, чтобы список был всегда виден, а не только при нажатии клавиши.
2. Найти причину Segmentation Fault в конце, может не освобождаю какие ресурсы FSOUND?
Или неверная работа с каналами?
3. Глюк в уровнях громкости для музыки и эффектов. Я его видел в сорце, только руки не дошли исправить сразу.

Но я и так доволен, как СЛОН! У меня всё получилось как я хотел.

Хинт: компиляция TranzAm в 32-битном режиме, 64 бита он не поддерживает
(где-то на уровне PPACol – коллизий, выделение памяти с учетом 32 битных указателей, а не 64 бит?
Да, и FancyFont тоже глючат, и переходы (FBLend?))

================================================================================================
$ date
Вс. июня 7 00:53:37 MSK 2015

Ох-хох, примерно час убил на компиляцию и разборку с TileExtractor. Вроде прикольная штука, всё получлось скомпилить, только файл тяжело в этой самой ADIME выбрать.

Также скачал Mappy для Windows, но ч/з Wine, как и было написано на сайте, он нормально пошёл. поигрался чуток, да и забросил.

Пока всё, пока!

Приготовлю архивчик с новыми файлами retrospec, всё подчищу.

====================================================================================================

 

BrainGames retro-игры под Linux

Здравствуйте.

Задача: взять все доступные игры на http://www.braingames.getput.com/
и собрать их под современный Линукс (modern Linux).

Задача решена успешно, игры классные, живые скриншоты всех игр я представлю!
Результаты моей работы – переделанные готовые для сборки сорцы, без объектных файлов,
можно скачать здесь: http://beotiger.com/download/braingames
Архивчик весит окло 80 Мегабайт, для некоторых игр включены их Windows-версии со всеми нужными библиотеками. Все Windows-версии игр Вы можете скачать с сайта BrainGames, адрес вверху. Я оставил Windows версии для сравнения.

Ниже русский текст перемежается с английским, сам не знаю почему.
Я – двуязычен, bilingual, хорошо, что не двуличен, хотя кто его знает! 🙂

Для сборки игр надо поставить в систему SDL: Simple DirectMedia Layer
(старый SDL, 1.2), а также некоторые сопутствующие ему либы, как то:
SDL_image SDL_mixer SDL_sound SGE etc.
причем их девелоперские версии (обычно оканчивающиеся на -dev или -devel)

В системах на основе APT'а (Debian/Ubuntu/Mint и другие), это делается так:
$ apt install build-essential libsdl-dev libsdl-image1.2-dev libsdl-mixer1.2-dev libsdl-sound1.2-dev libsdl-ttf2.0-dev libsdl-sge-dev

Начал я тогда с месяц, а то и более, назад:

Date: 7-14 May 2015 AD
System: Linux justy 3.13.0-37-generic #64-Ubuntu SMP Mon Sep 22 21:28:38 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

justy@justy ~/src/braingames $ c++ –version
c++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

ОК, у нас современный Линукс Минт (Linux Mint), который идентифицируется как Ubuntu, ну и хорошо,
и современный компилятор c++ 4.8 (это g++).

Да, в играх BrainGames Alt+Enter переключает полный экран/окно, F12 – быстрый выход из игры.

Поехали игры:
0. TransballGL – only demo for Windows? But in archive there is src directorty, that should be compiled later!?
OK, Makefile created, SDL_rotozoom.h not found, it the part of SDL_gfx?
Install libSDL-gfx1.2-4 ?

collision.cpp:28:20: fatal error: GLtile.h: No such file or directory
#include "GLtile.h"

OK, Makefile needed to be changed!

Смысл такой, что TransballGL – крутая штука, и надо собрать её под нашу систему,
но пока не знаем как. Что-то много всего отсуствует.
Но в итоге мне удалось его собрать, он идёт ближе к кноцу. Оно стоит того!

1. supertransball2: compiled without problems from SuperTransball/stransball2-v15-windows/stransball2sources/.
Эта игра – предшественник TransballGL, только графика попроще, и уровней поменьше.
Стоит того, чтобы поиграть пару-тройку уровней.

Как собирается:
$ cd braingames/SuperTransball/src
$ make
После этого исполняемый файл stransball2 будет перемещен в папку вверх.

чтобы поиграть, делаем
$ cd ..
$ ./stransball2
 

strb1.jpg

strb2.jpg

2. RoadFighter

Linking errors.
Need to change string in Makefile:
$(CC) $(LDFLAGS) $^ -o $@ to $(CC) $^ -o $@ $(LDFLAGS)
e.g. LDFLAGS should go last.

Then all's OK!

Да, в RoadFighter'е ошибки линкощика обнаружились,
новый GCC использует другой порядок линка? Не знаю точно.

Новый Makefile должен работать без проблем:
$ cd braingames/roadfighter
$ make
$ ./roadfighter

В директорию src заходить не нужно, Makefile расположен здесь, он сам распознает нужную папку.
Игра играет!

 

rf1.jpg

rf2.jpg

rf3.jpg

rf4.jpg

3. F1 Spirit

Same LDFLAGS issue as in RoadFighter.
Also: delete curl/types.h line (it's obsolete long time ago).
To avoid linking against libm and others libc++ libraries we should change default compiler from gcc to g++.

Да, те же проблемы с линком, что и у RoadFighter. Плюс ещё пара нюансов вылезло (см. выше, на английском).

Итого: игрушка супер, RoadFighter * 100, свои уровни, реальные гонки. Но не проста в прохождении.
На сайте написано, что не доделана, но 3 трассы играются на ура!

Собираем:
$ cd braingames/F-1\ Spirit/
$ make
$ ./f1spirit

То есть в sources, как и в случае с roadFighter, заходить не надо, игра собирается и запускается с корня.
Наслаждаемся:
 

f1s1.jpg

f1s2.jpg

f1s3.jpg

f1s4.jpg

f1s5.jpg

f1s6.jpg

4. The Goonies

Same LDFLAGS issue as in RoadFighter.
Same needing g++ compiler instead of gcc.
Then make is OK!

ОК, собираем:

$ cd braingames/TheGoonies
$ make
$ ./goonies
 

goon1.jpg

goon2.jpg

goon3.jpg

goon4.jpg

goon5.jpg

5. NETHER EARTH

Как я сначала компилировал, и какие ошибки исправил (на английском, не обесудьте):
Ниже будет сборка готовой игры на русском.

$ cd NETHER EARTH/Nether Earth v0.52/src
$ make
g++ -c cmc.cpp -o cmc.o
cmc.cpp:11:21: fatal error: GL/glut.h: No such file or directory
#include "GL/glut.h"
^
compilation terminated.
make: *** [cmc.o] Error 1

No glut dev lib?
OK:
$ sudo apt-get install freeglut3-dev freeglut3

Yep, now it compiles!

Now, after runnig I got following error:
freeglut ERROR: Function <glutStrokeWidth> called without first calling 'glutInit'.

In main.cpp in main function I added line:
glutInit(& argc, argv);

and added:
#include "GL/gl.h"
#include "GL/glut.h"
at the head of it.

OK, rm *.o && make done it well!
Nether Earth works now!

Да, для NetherEarth – крутой 3D ретро-стратегии – надо доустановить GLUT:

$ apt install freeglut3-dev
$ cd braingames/NETHER\ EARTH/src
$ make
$ cd ..
$ ./nether_earth

Смысл игры похоже – захватить все ресурсы или уничтожить вражескую базу?
Мы управляем каким-то подом, можем строить роботов из различных компонентов,
потом отдавать им приказы – захватывать ресурсы/уничтожать вражеских роботов и т.п.
Или управлять ими с помощью своего пода. Круто!
 

ne1.jpg

ne2.jpg

ne3.jpg

ne4.jpg

6. The Maze of Galious

Same $(LDFLAGS) as in RoadFighter.
All is OK!

В этой игрушке есть фишка: нажатие клавиши F10 меняет скины игры,
превращая её то в версию для Dendy, то в версию для MSX, то в современную ретро-версию и т.п.
Я насчитал 6 шкурок.

Итак, сборка проста:

$ cd braingames/The\ Maze\ of\ Galious/
$ make
$ ./mog
 

tmg1.jpg

То же самое с другой шкуркой:
 

tmg2.jpg

tmg3.jpg

tmg4.jpg

tmg5.jpg

Другая шкурка:

tmg6.jpg

7. Transball GL

Вот и добрались до неё!

Этапы начальной сборки игры показаны ниже, уже на русском.
Потратил наверное около часа на всё это.
Сборка игры сейчас описана ниже, там же идут скриншоты.

justy@justy ~/src/braingames/TransballGL/TGL/src $ make
g++ -w -c state_playerprofile.cpp -o state_playerprofile.o `sdl-config –cflags`
state_playerprofile.cpp: In member function ‘int TGLapp::playerprofile_cycle(KEYBOARDSTATE*)’:
state_playerprofile.cpp:120:7: error: ‘m_profile_profiles_names’ was not declared in this scope
m_profile_profiles_names.Add(tmp);
^
make: *** [state_playerprofile.o] Error 1

> Тут опечатка: не m_profile_profiles_names, а m_profile_profile_names

g++ -w -c XMLparser.cpp -o XMLparser.o `sdl-config –cflags`
XMLparser.cpp:19:20: fatal error: symbol.h: No such file or directory
#include "symbol.h"
^
compilation terminated.
make: *** [XMLparser.o] Error 1

> И опять опечатка, не symbol.h а Symbol.h
> Тоже самое было с GLtile.h (вместо GLTile.h)
> Linux это не Windows, тут регистр в именах файлов имеет значение

> Пришлось тж. добавлять #else include <dirent.h> etc. вместе с #ifdef _WIN…
> И вместо _mkdir и т.п. использовать mkdir в условных выражениях
> В некоторых файлах… где ругался на DIR и dirent и прочее, надо было делать так:

#ifdef _WIN32
#include "windows.h"
#else
#include <unistd.h>
#include <stddef.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include "ctype.h"
#endif

То есть под #else я тут подразумеваю Linux. Попробовать бы собрать под MacOS X!?

Игра в итоге собралась успешно и играет как надо, так что всё жуе позади!
Итак, собираем сейчас:

$ cd braingames/TransballGL/src
$ make
$ cd ..
$ ./tgl

Цель игры – управляя мини-ракетой, захватить шарик, избегая любых препятствий и вытащить его на самый верх уровня.
Любое столкновение, кроме шарика, карается моментальной гибелью и переигрыванием всего уровня.

Кроме того, ещё расходуется горючее, за которым надо следить на некоторых уровнях.

Клавиши управления можно переназначяить в меню. Выбор любого пройденного уровня теперь осуществляется легко,
не надо запоминать пароли, как для SuperTransball2.

Уровни есть те же, что и в SuperTransball2, а есть я так понял и новые, но до них я пока не дошёл.

 

trgl1.jpg

trgl2.jpg

trgl3.jpg

trgl4.jpg

И на закуску –

8. Magical Tree

Эта игра не доделана и вряд ли когда будет.
К сожалению, исходники не представлены, мне по крайней мере не удалось их найти.

Играется через WINE:

$ cd braingames/Magical\ Tree/
$ wine Demo.exe

Доходит до конца дерева, и всё, даже если все яблоки собрал.
 

mt1.jpg

mt2.jpg

mt3.jpg

Пока всё, от BrainGames ничего не слышно уже лет 6, с 2009 года. Жаль, классные римэйки делали!
И сорцы крутые!

Спасибо вам, господа из BrainGames за наше счастливое дество!

$ date
Пн. июня 8 22:31:04 MSK 2015

$ uname -a
Linux justy 3.13.0-51-generic-tuxonice #84~ppa1-Ubuntu SMP Wed Apr 29 19:39:16 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

$ g++ –version
g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ free -gho
total used free shared buffers cached
Память:7,8G 2,8G 5,0G 53M 49M 1,0G
Swap: 3,0G 0B 3,0G

~/src $ zip -r9 braingames.zip braingames/

$ du -sh *.zip
78M braingames.zip
34M retrospec.zip
 

Моя статья в Хакер “Заморозь своего пингвина”

Предисловие

Здравствуйте.
Почти 8 лет назад в журнале Хакер 2007 года за сентябрь (№105) была опубликована моя статья. Как она создавалась? Я уже сейчас не помню точно, помню только, что я увлекался Линуксом тогда и мне понравился Suspend2 (ныне TuxOnIce), я настроил его у себя в Gentoo и у меня всё получилось. Это было круто и я захотел поделиться с сообществом по теме. моим любимым журналом тогда был “Хакер” (сейчас – LinuxFormat), там был раздел Unixoid. Я связался с редактором раздела, объяснил ему тему, он мне ответил что в принципе тема неплоха, давай попробуем. Объяснил условия, формат статьи и её объем максимальный. Что в итоге – я всё сделал по их стандартам (журнала Хакер), выслал им архивчик, и моя статья была опубликована в Хакере №9 (105) от 2007 года – https://xakep.ru/issues/xa/105

Статья

Статья назвается “Заморозь своего пингвина – отправляем Линукс в спячку”. Правда почему-то рядом с моим именем красовлось какое-то имя Goabruce (написано было GOABRUCE & BEOM BEOTIGER). Я написал редактору, что за goabruce и как он тут оказался, ведь статью писал и компоновал всё в ней я один (редактор только её урезал). Он ответил, мол, извините ошибка вышла. Это просто фантастика. За всё время чтения журнала Хакер я такого больше не встречал. Ну да ладно, Бог с этим goabruce’ом, кто бы он ни был. Может он и правда во сне помогал мне делать эту статью.

Буду краток как никогда. В статье рассказывалось о новом методе погружения Линукса в сон (hibernation), названным автором Suspend2. Суть его в том, что текущая RAM системы записывается на диск (в файл или раздел подкачки), и компьютер выключается/перезагружается, а при повторном входе в систему память полностью восстанавливается как есть с диска – и всё текущее окружение становится доступным сразу. то есть все открытые программы, процессы, окна и т.п. при таком входе в систему остаются на месте, и ты можешь продолжить работу как есть, как будто компьютер вовсе не выключался на ночь (или день, смотря кто когда работает).

Круто? Да, круто. Удобно? Несомненно. Да просто супер!

Сегодня

Итак, после большого перерыва, когда я пользовался Linux’ом только время от времени (в виртуальных машинах), с 2008 по 2015 год, когда я поставил себе сначала Kubuntu, потом снес её и установил Linux Mint, чему несказанно рад сейчас, мне на глаза попалась эта моя старая позабытая сейчас уже статья. Ради интереса я подумал, а что там с Suspend2 – заглянул на сайт http://www.suspend2.net, бывший визитной карточкой проекта, а там реклама – он на продажу!

Я подумал, проект загнулся, автор утратил к нему интерес, как часто бывает с открытыми проектами, не приносящими прибыль, потом на глаза мне попалось словосочетание TuxOnIce. Пингвин на Льду? Правильнее было бы назвать – TuxInIce – пингвин во льду. поиск tuxonice в гугле вывел на страничку, до боли знакомую – http://tuxonice.nigelcunningham.com.au Так вот же он, мой родной suspend2! Для прикола я решил попробовать, получится ли у меня поставить его на свой Mint, только без перекомпиляции ядра и всеми прочими долгими настройками, что описывались в моей статье.

Сделал по инструкции на сайте – у них есть прекомплированная версия для Ubuntu (а Mint 100% совместим с Юбунту, по крайней мере так я прочитал в руководстве по Минту), устанавливаемая через PPA – крутая штука, из-за которой я променял Деби на Убунту, а потом Убунту на Минт. Здесь – https://launchpad.net/~tuxonice/+archive/ubuntu/ppa

Просто apt install linux-generic-tuxonice tuxonice-userui, потом выполнил команду “sudo pm-hibernate” и … ничего. Блин, обидно, не работает. Ещё на каком то источнике по теме я прочитал слово “reboot”, перезагрузился, попробовал снова sudo pm-hibernate и всё заработало. Линукс мой ушел в спячку, а потом вернулся волшебным образом. И сейчас я пользуюсь TuxOnIce без проблем (где-то с месяц наверное, правда у меня раздел подкачки около 4 гигов против 8 гигов RAM, как бы это проблем не вызвало, если память будет моя загружена достаточно – а разбираться с подменой образа честно лень пока).

Сама статья

А в качестве бонуса я публикую здесь свою как есть, без купюр, тем более тот номер Хакера от 2007 года/сентябрь давно доступен для скачивания бесплатно с сайта xakep.ru – https://xakep.ru/issues/?y=2007

Скачать оригинал статьи от 2007 года вместе с рабочими материалами и скриншотами можно здесь: http://beotiger.com/download/xakep_article2007

Заморозь своего пингвина.

Предыстория.

Иногда бывают такие моменты, когда у тебя открыто с десяток окон, ты весь в работе, у тебя что-то компилируется, редактируется, играется, и тут пришла пора срочно выключить компьютер, например, внезапно появляется младший брат жены и просит дать ему поиграть, или ты взглянул на часы, и увидел что уже пять утра и пора бы пойти спать. В такие моменты хочется просто заморозить свою систему, чтобы при следующем включении компьютера или перезагрузки системы вернуться в то место, где остановился, и мог безболезненно продолжить процесс.

В этом случае на помощь придёт Suspend2 (http://www.suspend2.net). Почему именно он? Во-первых, это активно развивающийся и успешный проект Найджэла Канингхэма (Nigel Cunningham), Бернарда Блэкхэма (Bernard Blackham), Флоренца Шобо (Florent Chabaud) и многих других, который в своё время отделился от swsusp и сейчас развивается независимо. Во-вторых, он обладает вкусностями, мимо которых не может пройти ни один заядлый линуксоид, да и просто любитель компьютеров. Вот основные из них:

  • Динамическая и быстрая компрессия образа памяти (по умолчанию используется метод LZF).
  • Полная поддержка асинхронного или предупреждающего чтения-записи
  • Поддержка любого количества своп-разделов или файлов.
  • Возможность безопасно прервать процесс засыпания нажатием клавиши ESC.
  • Возможность записи полного образа памяти
  • Поддержка сжатия и кодирования записываемого образа.
  • Доброжелательный графический интерфейс.
  • Поддержка больших объёмов памяти (на настоящий момент – вплоть до 4 Гигабайт), многопроцессорных систем.
  • Поддержка скриптов.
  • Может быть полноценной заменой стандартному swsusp.

Если вкратце, то Suspend2 сохраняет содержимое RAM компьютера и выключает питание. При последующем включении он восстанавливает содержимое RAM, и вы можете продолжать работу как ни в чём не бывало – нет необходимости снова запускать программы, открывать документы, терминалы и т.д. и т.п.

Что нужно для успешной установки и работы Suspend2? В принципе, если у вас современный компьютер на базе процессора Pentuim и IDE диски, а так же свежее ядро ветки 2.6, то с большой вероятностью Suspend2 будет работать без проблем. В частности, для корректной работы необходима поддержка процессором pse или pse36 (page size extensions).

Проверяем:

$ cat /proc/cpuinfo | grep flags

flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe cid xtpr

В данном случае процессор (а это относительно старенький Celeron 2ГГц), имеет поддержку и того, и другого.

Скриншот 1: Основная страница проекта Suspend2.

Как уже упоминалось, проект отделился от swsusp, но, к сожалению, по некоторым разногласиям среди кёрнел-хакеров, в отличие от последнего не включён в ванильные ядра, и чтобы использовать Suspend2, нам надо будет наложить патч и перекомпилировать ядро.

Готовим ядро.

Да. Если вы никогда раньше не компилировали ядро своему любимому Пингвину… что ж, самое время сделать это сейчас. Как говорится, всё всегда когда-нибудь бывает в первый раз. Тем более процедура компиляции ядра не такая сложная и утомительная, как может показаться на первый взгляд. Но, поначалу, конечно, всё будет не так просто. Главное, помните, что не следует сжигать мосты за собой, то есть не удаляйте ваше текущее рабочее ядро из /boot и ссылки на него из загрузчика, пока не убедитесь в течение достаточного времени, что новое ядро, которое вы сами откомпилировали, работает без проблем. Ссылки на статьи по конфигурировании и компиляции ядра в Линуксе вы можете найти во врезке.

Итак, сперва убедитесь, что исходники работающего в данный момент ядра лежат в /usr/src/linux (дефолтовое место для большинства линукс-дистрибутивов).

Смотрим:
$ uname -a
Linux beoplanet 2.6.19.2 #3 Mon May 14 17:09:01 MSD 2007 i686 Intel(R) Celeron(R) CPU 2.00GHz GenuineIntel GNU/Linux
$ file /usr/src/linux
/usr/src/linux: symbolic link to `linux-2.6.19.2'
$ ls /usr/src/linux
arch Documentation ipc Makefile REPORTING-BUGS usr
block drivers Kbuild mm scripts vmlinux
COPYING fs kernel Module.symvers security
CREDITS include lib net sound
crypto init MAINTAINERS README System.map

Здесь мы видим, что у нас рабочее ядрышко 2.6.19.2, а символическая ссылка (/usr/src/linux) указывает на каталог с исходниками именно для этой версии.

Если у вас нет каталога /usr/src/linux, или он пуст, значит, исходники ядра скорее всего просто не установлены в вашей системе. Ничего страшного. Давно пора перейти на свежее ядро, тем более что на каждом диске журнала "Хакер" есть новые ванильные ядра Пингвина. А именно ванильные ядра (то есть истинные, чистые ядра с kernel.org безо всяких патчей, одобренные самим Линусом Торвальдсом) наиболее точно подходят Suspend2! (почему – читайте ниже). Скачиваем свежее ядро с kernel.org, распаковываем его в /usr/src/ и делаем на него симлинк /usr/src/linux.

Обратите внимание на версию ядра. В данный момент на основной странице закачки Suspend2 для версии 2.2.10 предлагаются патчи для следующих версий ядер: 2.6.18.8, 2.6.19.7, 2.6.20.11, 2.6.21.1, 2.6.22-rc1 и ubuntu-feisty.

Для других версий вы можете поискать патчи здесь: http://www.suspend2.net/downloads/all/.

Замечания для владельцев Линукса на базе ядер 2.4. С главной страницы Suspend2 были убраны все ссылки на патчи для этих версий, потому что были сообщения о разрушении файловых систем при их использовании.

Помимо всего прочего, если вы пользователь Gentoo/GNU Linux, то для вас уже есть пропатченные ядра. Просто выполняем команду:
# emerge suspend2-sources

и патчить ядро нам уже не нужно (то есть можно сразу переходить к настройке и компиляции ядра).

Для пользователей последних версий Fedora Core и Red Hat так же есть готовое решение:
# yum install kernel-suspend2

В этом случае штатный инсталлятор всё сделает за вас – вам надо будет только перезагрузиться и использовать hibernate.

Накладываем патч.

Скриншот 2: Страница для закачки патчей и скриптов.

Итак, мы убедились, что у нас установлены исходники рабочего ядра. Если вы используете новое ядро, сначала убедитесь в его работоспособности (отконфигурируйте, откомпилируйте, установите его и загрузитесь с него).

Пришло время наложить патч Suspend2. Идём на http://www.suspend2.net/downloads, выбираем подходящий под нашу версию ядра патч, скачиваем его, например, в нашем случае для версии 2.6.19.2 скачиваем suspend2-2.2.9-for-2.6.19.patch.bz2. В общем случае, ядра версий 2.6.X.Y не слишком отличаются от версий 2.6.X, поэтому возможно использование одного и того же патча.

# wget http://www.suspend2.net/downloads/all/suspend2-2.2.9-for-2.6.19.patch.bz2 -P /tmp
Командуем:
# cd /usr/src/linux
# bzcat /tmp/suspend2-2.2.9-for-2.6.19.patch.bz2 | patch -p1
(путь и версия патча в вашем случае могут быть другими).

Если вы подобрали правильную версию, то никаких отклонений быть не должно. Если у вас не ванильные ядра, а скорее всего так оно и есть, ибо почти каждый дистрибутив использует собственные пропатченные версии, то может возникнуть несколько несоответствий (режектов). В этом случае у вас есть три возможности: или найти пропатченные версии ядер для вашего дистрибутива, или вручную пропатчить те файлы, в которых найдены несоответствия, либо… верно, установить ванильное ядро и начать всё сначала.

Компилируем ядро.

Теперь делаем make menuconfig, загружаем нашу текущую рабочую конфигурацию и приступаем к настройке поддержки Suspend2 в ядре.

Сперва убедимся, что включён Prompt for development and/or incomplete code/drivers в секции Code Maturity, включающий некоторые тестовые опции в конфигурировании ядра. Затем заходим в секцию Power management options (ACPI, APM) и видим там новый пункт Suspend2. Отмечаем его, и тут же заходим в подменю.

Здесь нужно сделать паузу и решить, что мы будем использовать в качестве буфера – специальный файл на жёстком диске или раздел подкачки. За это отвечают две опции: File Allocator и Swap Allocator. В принципе, можно отметить оба пункта, и решать откуда грузиться, непосредственно в самом загрузчике (см. далее). Но должен быть отмечен хотя бы один пункт! Другие опции можно оставить как есть, но, забегая вперёд, скажу, что если при восстановлении со свопа в загрузчике вы не хотите указывать девайс свопа, можно сделать это здесь, в пункте Default resume device name задав имя свопа, например, так: swap:/dev/hdb4, где /dev/hdb4 и есть раздел файла подкачки (в вашем случае он, скорее всего, будет другим).

Теперь идём в раздел Cryptographic options, находим пункт LZF compression algorithm и включаем его. Заметьте, что он должен быть встроен непосредственно в ядро, а не включен в виде модуля, иначе сжатие не будет работать.

Также, если у вас карточка от Nvidia на шине AGP, и вы не хотите при пробуждении лицезреть тёмный экран, необходимо в ядре отключить agpgart – поддержку AGP, включённую по умолчанию, тем более что у драйверов от Nvidia есть своя поддержка этой шины. Итак, заходим в секцию Device Drivers, подсекцию Character devices, там находим пункт /dev/agpgart (AGP Support) и выключаем его.

Скриншот 3: Конфигурируем ядро.

Если эта версия ядра не использует Initrd/Initramfs, то здесь можно сохраняться и компилировать своё ядро:

#make && make modules_install

и переходить к следующему пункту.

Если же вы используете Initrd/Initramfs, то вам надо будет вручную включить пробуждение: или модифицировать создание initrd/ramfs вашего дистро, или изменить скрипт linuxrc или init, включив туда следующую строчку:

echo 1 > /sys/power/suspend2/do_resume

ВАЖНО: эта строчка должна идти ПЕРЕД тем, как initrd/ramfs монтирует файловую систему! Если этой строчки нет, пробуждение не будет возможным, если же эта строчка идёт ПОСЛЕ монтирования файловой системы, она (файловая система) может быть разрушена! Помните об этом, и будьте осторожны.

Чтобы получить дополнительную информацию об initrd почитайте Documentation/initrd.txt (из каталога исходников ядра).

Предварительная настройка Suspend2

Теперь, прежде чем перезагружаться, необходимо провести первоначальную настройку Suspend2.

Управлять Suspend2 можно через виртуальный каталог /sys/power/suspend2, составляя свои скрипты для пробуждения/восстановления системы, но удобнее всё же будет воспользоваться готовым решением – hibernate-скриптом, который всю работу будет делать за нас.

Скачиваем hibernate-скрипт и устанавливаем его:

#wget http://www.suspend2.net/downloads/all/hibernate-script-1.95.tar.gz -P /tmp
#tar xzf /tmp/hibernate-script-1.95.tar.gz
#cd /tmp/hibernate-script-1.95
#./install.sh

Сам скрипт по умолчанию инсталлируется в /usr/sbin (это можно изменить в install.sh), а конфигурационные файлы (их может быть несколько) инсталлируются в каталог /etc/hibernate/.

Для пользователей Gentoo и Debian дистрибутивов уже есть включённый в их дистрибутивы hibernate-script.

В случае Gentoo делаем

#emerge hibernate-script

А в Debian (и ему подобных) что-то типа этого:

#apt-get install hibernate

По умолчанию настройки Suspend2 разбиты на три файла конфигураций: hibernate.conf, suspend2.conf и common.conf. В принципе, никто не мешает нам собрать их все в один главный файл (hibernate.conf), но мы пойдём по пути наименьшего сопротивления 😉 .

Начнём с первого и отредактируем файл /etc/hibernate/hibernate.conf

#vim /etc/hibernate/hibernate.conf

TryMethod suspend2.conf
#TryMethod disk.conf
#TryMethod ram.conf

Так как мы используем Suspend2, оставляем только его, disk.conf и ram.conf нам не понадобятся.

Дальше смотрим файл /etc/hibernate/suspend2.conf

#vim /etc/hibernate/suspend2.conf

UseSuspend2 yes
Reboot no
EnableEscape yes
DefaultConsoleLevel 1
Compressor lzf
Encryptor none

Include common.conf

Здесь находятся общие для Suspend2 настройки. Перечислю лишь основные из них.

Первая строчка UseSuspend2 yes говорит, что мы собираемся использовать именно Suspend2 (а иначе зачем мы вообще патчили наше ядрышко? 😉 )

Опция Reboot решает, хотим ли мы перезагружаться сразу после заморозки.
Опция EnableEscape yes позволит нам отменить процесс заморозки нажатием клавиши ESC.
Опция DefaultConsoleLevel 1определяет вид отображения при заморозке и разморозке (0 – простой прогресс-бар, 1 – прогресс-бар с процентами, 2 и выше выдаёт обильную отладочную информацию о происходящем).
Опции Compressor и Encryptor определяют методы сжатия и шифрования образа. Их имена можно узнать, выполнив команду #cat /proc/crypto.

Остальные настройки здесь вы можете править по вкусу или оставить их как есть, подробную информацию о них вы можете узнать из man(5)hibernate.conf:

$ man 5 hibernate.conf

Теперь переходим к основным настройкам, собранным в файле /etc/hibernate/common.conf:

Подробнее остановлюсь на, пожалуй, самых важных из них, остальные вы так же можете изменить по вкусу, сверяясь с man(5)hibernate.conf.

# vim /etc/hibernate/common.conf

UnmountFSTypes – здесь можно перечислить типы файловых систем, которые нужно размонтировать перед заморозкой, например, UnmountFSTypes smbfs nfs ntfs vfat. Смотрите ниже, раздел Подводные камни, зачем это может понадобиться. В принципе, если у вас есть чётко заданные устройства, можно размонтировать их в пункте Unmount (например, Unmount /media/winC /media/MyHomeNetwork)

Их же можно смонтировать обратно при пробуждении в пункте Mount (Mount /media/winC /media/MyHomeNetwork), иначе при пробуждении Suspend2 не сделает это автоматически.

Пункт UnloadModules позволяет перечислить модули, которые обязательно надо выгрузить перед заморозкой, но можно воспользоваться пунктами UnloadAllModules yes для выгрузки всех модулей, или UnloadBlacklistedModules yes для выгрузки тех модулей,чьи имена перечислены в файле /etc/hibernate/blacklisted-modules. Пункт LoadModules позволяет задать имена модулей, загружаемых при пробуждении (LoadModules auto автоматически загрузит все модули, которые были выгружены).

В пункте DownInterfaces можно указать сетевые интерфейсы, которые надо будет отключить перед засыпанием, а UpInterfaces auto автоматически запустит все остановленные интерфейсы при пробуждении.

Пункт RestartServices позволяет останавливать/запускать перечисленные здесь службы. Имена служб должны соответствовать названиям скриптов в каталоге init.d и быть активными на данном уровне запуска (runlevel).

SwitchToTextMode позволяет во время засыпания переключаться в текстовый режим, а при пробуждении возвращаться обратно к X'ам. Это может быть полезно, если BIOS при пробуждении не восстанавливает ваш графический адаптер, и ядро не может его опознать.

Опция UseDummyXServer также может помочь в ряде случаев, когда, например, при пробуждении на некоторых видеокартах наблюдается потеря ускорения в 3D графике.

Параметрами в IncompatiblePrograms вы можете указать программы, которые по каким либо причинам не совместимы с Suspend2, в этом случае, если Suspend2 обнаружит, что такая программа выполняется в настоящий момент времени, он отменит заморозку.

Также можно запереть вход в систему после пробуждения, одним из параметров в опциях LockConsoleAs, LockXScreenSaver, LockGnomeScreenSaver, LockKDE, LockXLock, LockXAutoLock (в таком случае правильным будет определить лишь один из вышеперечисленных параметров). Если вы это сделаете, то после пробуждения необходимо будет вновь залогиниться, чтобы продолжать работать.

Наконец, если в опции XStatus вы укажете одно из значений (kde, gnome или x), то Suspend2 будет выводить прогресс-бар при засыпании/пробуждении, а также выдавать сообщения об ошибках в окошках для указанной графической среды.

Скриншот 4: Настраиваем конфиг.

Итак, мы закончили настройку Suspend2 и можно уже переходить в настройке загрузчика и перезагрузки в Suspend2. Но если вы решили использовать не раздел подкачки, а файл в качестве буфера для сохранения RAM, то его сперва необходимо подготовить. Делается это так:

В /etc/hibernate/suspend2.conf ищем строку FilewriterLocation, раскомментируем её и переделываем по своему вкусу, например, так:

FilewriterLocation /var/suspend_file 1024

Здесь первый параметр – это имя файла под буфер, второй – его размер в мегабайтах. Обычно его размер можно указывать равным объёму оперативки вашего бокса – не забудьте, что Suspend2 сжимает сохранённый образ RAM!

Теперь командуем:

#hibernate –no-suspend

и Suspend2 сам подготовит для нас файл. Смотрим, что выдаёт /sys/power/suspend2/resume2

#cat /sys/power/suspend2/resume2

Это может быть что-то типа file:/dev/hda1:0x10011f. Записываем или запоминаем эту строчку – она нам позже понадобится при конфигурировании загрузчика.

Ещё случай – использование файла подкачки. Его также можно использовать в качестве буфера. Настраивается это следующим образом:

В файле /etc/hibernate/suspend2.conf находим и заполняем следующий пункт:

SuspendDevice swap:/dev/hda3/swap_file

Запускаем:

# hibernate –no-suspend.

Смотрим:

# cat /sys/power/suspend2/swap/headerlocations

Мы можем получить что-то типа swap:/dev/hda3:0xfd400. Также записываем или запоминаем эту строчку и сперва укажем её в /etc/hibernate/suspend2.conf:

SuspendDevice swap:/dev/hda3:0xfd400

В случае изменения местоположения файла подкачки, или если вы его удалили, а потом вновь восстановили, вам необходимо будет вновь свериться с /sys/power/suspend2/swap/headerlocations, чтобы узнать его новые координаты (для файлов Suspend2 запоминает абсолютное расположение их на жёстком диске).

Эти новые координаты необходимо будет прописать в конфиге и в загрузчике (смотрите ниже).

Настройка загрузчика

Итак, мы откомпилировали ядро и поместили его в /boot, например так: cp arch/i386/boot/bzImage /boot/kernel-2.6.19.2suspend2 (имя по вашему желанию).

Теперь указываем на него в загрузчике в опции kernel, и добавляем туда строчку resume2=указание на ваш буфер (своп или файл).

Если вы используете своп, это может выглядеть так: resume2=swap:/dev/hdb4

Если же вы решили использовать файл, сюда надо подставить значение из /sys/power/suspend2/resume2 с префиксом file:, то есть это может выглядеть так: resume2=file:/dev/hda1:0x10011f.

Если это своп-файл, то строчка может выглядеть так: resume2=swap:/dev/hda3:0xfd400

Вся секция (в случае использовании свопа на /dev/hdb4) может выглядеть так (при использовании grub):

title Wake UP! (Gentoo Linux – kernel 2.6.19.2 with Suspend2)
root (hd0,0)
kernel /boot/kernel-2.6.19.2suspend2 root=/dev/hdb1 init=/sbin/init quiet resume2=swap:/dev/hdb4

В вашем случае имена разделов и образа ядра могут быть другими.

В lilo это же надо указывать примерно так:

image = /boot/ kernel-2.6.19.2suspend2
label = Wake UP! (Gentoo Linux – kernel 2.6.19.2 with Suspend2)
append = "resume2=swap:/dev/hdb4"

Также рекомендуется иметь «запасную» секцию в случае, если вы не захотите пробуждаться (в случае засыпания) или думаете, что файловая система,используемая при работе заснувшим ядром, была каким-то образом изменена (об этом читайте далее, в Подводных камнях). В этом случае параметр kernel будет выглядеть так же, но к нему надо просто добавить noresume2.

Такая секция может выглядеть, например, так (опять же, если мы используем grub в качестве загрузчика):

title Boot without resume (Gentoo Linux – kernel 2.6.19.2 with Suspend2)
root (hd0,0)
kernel /boot/kernel-2.6.19.2suspend2 root=/dev/hdb1 init=/sbin/init quiet resume2=swap:/dev/hdb4 noresume2

Для lilo:
image = /boot/ kernel-2.6.19.2suspend2
label = Wake UP! (Gentoo Linux – kernel 2.6.19.2 with Suspend2)
append = "resume2=swap:/dev/hdb4 noresume2"
append = "noresume2"

Не забудьте, если вы используете lilo, каждый раз после изменения lilo.conf презапускать lilo:
#/sbin/lilo

Теперь вы всегда сможете загрузить систему без пробуждения, выбрав строчку Boot without resume.

Итак, у нас всё готово. Но сперва необходимо убедиться, что мы всё сделали верно, и можем использовать Suspend2. Для этого сначала необходимо просто перезагрузиться в новом ядрышке (если вы сделали два пункта – без noresume2 и с ним, как мы советовали, можно выбрать любой из них – Suspend2 сам распознаёт готовность системы к пробуждению), и смотрим лог ядра:

$ dmesg | grep Suspend2

Suspend2 Core.
Suspend2 Userspace UI Support module loaded.
Suspend2 Checksumming module loaded.
Suspend2 Userspace Storage Manager module loaded.
Suspend2 Compressor module loaded.
Suspend2 Encryptor module loaded.
Suspend2 Block I/O module loaded.
Suspend2 Swap Allocator module loaded.
Suspend2 2.2.9: SwapAllocator: Signature found.
Suspend2 2.2.9: Resuming enabled.
Suspend2 2.2.9: Normal swapspace found.
Suspend2 2.2.9: No image found.

Обратите внимание на строчку Suspend2 2.2.9: Resuming enabled. Она показывает, что наш пингвин готов к заморозке/разморозке! Несмотря на это, впервые для апробирования этой фичи рекомендуется усыпить систему без X'ов.

Переходим на текстовую виртуальную консоль (Alt+Ctrl+F1) , закрываем X'ы, например, так

# /etc/init.d/xdm stop (или # init 3, если у вас Red Hat, Fedora или Mandrake)

и делаем:

#hibernate

Если засыпания не состоялось (например, Suspend2 не смог выгрузить модуль – а он сообщит об этом на экране или в логе (по умолчанию в /var/log/hibernate.log), можно форсировать процесс:

#hibernate –force

и Suspend2 должен сделать свою работу в любом случае.